From 6b40c8de70174b412e223b1f40746f23b2277b52 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:11:58 +0800 Subject: [PATCH 001/163] New translations readme.md (Uzbek) [skip ci] Update translations (Uzbek) readme.md --- uz_UZ/README.md | 101 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 uz_UZ/README.md diff --git a/uz_UZ/README.md b/uz_UZ/README.md new file mode 100644 index 000000000..e7dccf1e6 --- /dev/null +++ b/uz_UZ/README.md @@ -0,0 +1,101 @@ +
+ +Logo + +[![Doc](https://pkg.go.dev/badge/github.com/goravel/framework)](https://pkg.go.dev/github.com/goravel/framework) +[![Go](https://img.shields.io/github/go-mod/go-version/goravel/framework)](https://go.dev/) +[![Release](https://img.shields.io/github/release/goravel/framework.svg)](https://github.com/goravel/framework/releases) +[![Test](https://github.com/goravel/framework/actions/workflows/test.yml/badge.svg)](https://github.com/goravel/framework/actions) +[![Report Card](https://goreportcard.com/badge/github.com/goravel/framework)](https://goreportcard.com/report/github.com/goravel/framework) +[![Codecov](https://codecov.io/gh/goravel/framework/branch/master/graph/badge.svg)](https://codecov.io/gh/goravel/framework) +![License](https://img.shields.io/github/license/goravel/framework) + +
+ +English | [中文](/zh_CN/README.md) + +## About Goravel + +Goravel is a full-featured, scalable web application framework that provides a starting scaffold to help Gophers quickly build their applications. + +The framework style is consistent with [Laravel](https://laravel.com/), so PHP developers don’t need to learn a new framework and can still enjoy playing around with Golang, in tribute to Laravel! + +We welcome stars, PRs, and issues! + +## Documentation + +Online documentation [https://www.goravel.dev](https://www.goravel.dev) + +Example [https://github.com/goravel/example](https://github.com/goravel/example) + +> To optimize the documentation, please submit a PR to the documentation +> repository [https://github.com/goravel/docs](https://github.com/goravel/docs) + +## Main Features + +| Module Name | Description | +| -------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | +| [Artisan Console](https://www.goravel.dev/digging-deeper/artisan-console.html) | CLI command-line interface for application management and automation | +| [Authentication](https://www.goravel.dev/security/authentication.html) | User identity verification with JWT and Session drivers | +| [Authorization](https://www.goravel.dev/security/authorization.html) | Permission-based access control using policies and gates | +| [Cache](https://www.goravel.dev/digging-deeper/cache.html) | Store and retrieve data using memory, Redis, or custom drivers | +| [Carbon](https://www.goravel.dev/digging-deeper/helpers.html) | Helper functions for date and time manipulation | +| [Config](https://www.goravel.dev/getting-started/configuration.html) | Application configuration management from files and environment | +| [Crypt](https://www.goravel.dev/security/encryption.html) | Secure data encryption and decryption utilities | +| [DB](https://www.goravel.dev/database/getting-started.html) | Database query builder | +| [Event](https://www.goravel.dev/digging-deeper/event.html) | Application event dispatching and listening system | +| [Factory](https://www.goravel.dev/orm/factories.html) | Generate fake model data for testing purposes | +| [FileStorage](https://www.goravel.dev/digging-deeper/filesystem.html) | File upload, download, and storage across multiple drivers | +| [Grpc](https://www.goravel.dev/the-basics/grpc.html) | High-performance gRPC server and client implementation | +| [Hash](https://www.goravel.dev/security/hashing.html) | Secure password hashing | +| [Http](https://www.goravel.dev/the-basics/routing.html) | HTTP routing, controllers, and middleware management | +| [Http Client](https://www.goravel.dev/digging-deeper/http-client.html) | Make HTTP requests to external APIs and services | +| [Localization](https://www.goravel.dev/digging-deeper/localization.html) | Multi-language translation and locale management | +| [Logger](https://www.goravel.dev/the-basics/logging.html) | Application logging to files, console, or external services | +| [Mail](https://www.goravel.dev/digging-deeper/mail.html) | Send emails via SMTP or queue-based delivery | +| [Mock](https://www.goravel.dev/testing/mock.html) | Create test mocks for facades and dependencies | +| [Migrate](https://www.goravel.dev/database/migrations.html) | Version control for database schema changes | +| [Orm](https://www.goravel.dev/orm/getting-started.html) | Elegant Orm implementation for database operations | +| [Package Development](https://www.goravel.dev/digging-deeper/package-development.html) | Build reusable packages to extend framework functionality | +| [Process](https://www.goravel.dev/digging-deeper/process.html) | An expressive and elegant API around Go's standard `os/exec` package | +| [Queue](https://www.goravel.dev/digging-deeper/queues.html) | Defer time-consuming tasks to background job processing | +| [Seeder](https://www.goravel.dev/database/seeding.html) | Populate database tables with test or initial data | +| [Session](https://www.goravel.dev/the-basics/session.html) | Manage user session data across HTTP requests | +| [Task Scheduling](https://www.goravel.dev/digging-deeper/task-scheduling.html) | Schedule recurring tasks using cron-like expressions | +| [Testing](https://www.goravel.dev/testing/getting-started.html) | HTTP testing, mocking, and assertion utilities | +| [Validation](https://www.goravel.dev/the-basics/validation.html) | Validate incoming request data using rules | +| [View](https://www.goravel.dev/the-basics/views.html) | Template rendering engine for HTML responses | + +## Compare With Laravel + +[For Detail](https://www.goravel.dev/prologue/compare-with-laravel.html) + +## Roadmap + +[For Detail](https://github.com/goravel/goravel/issues?q=is%3Aissue+is%3Aopen) + +## Excellent Extend Packages + +[For Detail](https://www.goravel.dev/getting-started/packages.html) + +## Contributors + +This project is made possible by everyone who contributes. To contribute, please consult the [Contribution Guide](prologue/contributions.md). + + + +## Sponsor + +Better development of the project is inseparable from your support, reward us by [Open Collective](https://opencollective.com/goravel). + +

+ +## Group + +Welcome more discussion in Discord. + +[https://discord.gg/cFc5csczzS](https://discord.gg/cFc5csczzS) + +## License + +The Goravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). From b99915eacaac0d494ac05c17c1bdbc9db004b0fb Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:11:59 +0800 Subject: [PATCH 002/163] New translations facades.md (Uzbek) [skip ci] Update translations (Uzbek) facades.md --- uz_UZ/architecture-concepts/facades.md | 68 ++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 uz_UZ/architecture-concepts/facades.md diff --git a/uz_UZ/architecture-concepts/facades.md b/uz_UZ/architecture-concepts/facades.md new file mode 100644 index 000000000..49f6569f5 --- /dev/null +++ b/uz_UZ/architecture-concepts/facades.md @@ -0,0 +1,68 @@ +# Facades + +[[toc]] + +## Introduction + +`facades` provide a "static" interface for the core functionality of the application and provide a more flexible, more elegant, and easy-to-test syntax. All `facades` of Goravel are defined under the `app/facades` folder: + +```go +import "app/facades" + +facades.Config().GetString("app.host") +``` + +## How Facades Work + +Each service provider registers its corresponding bindings in the service container, then the service container providers vairous `Make*` functions to build the binding instances. The `facades` in the `app/facades` folder call these `Make*` functions to get the instances from the service container. Let's use the `Route` facade as an example: + +1. The `Route` service provider registers the `binding.Route` binding in the service container: + +```go +type ServiceProvider struct {} + +func (r *ServiceProvider) Register(app foundation.Application) { + app.Singleton(binding.Route, func(app foundation.Application) (any, error) { + return NewRoute(app.MakeConfig()) + }) +} + +func (r *ServiceProvider) Boot(app foundation.Application) {} +``` + +2. The `Route` facade calls the `MakeRoute()` function to get the `Route` instance from the service container: + +```go +// app/facades/route.go +package facades + +import ( + "github.com/goravel/framework/contracts/route" +) + +func Route() route.Route { + return App().MakeRoute() +} +``` + +> Given that the `facades` is exposed to the application, you can also create your own `facades` or override the existing `facades` in the `app/facades` folder. + +## Install/Uninstall Facades + +[goravel/goravel](https://github.com/goravel/goravel) installs all `facades` by default and [goravel/goravel-lite](https://github.com/goravel/goravel-lite) only installs essential `facades` like `Artisan`, `Config`. You can install or uninstall other `facades` as needed via the `package:install` and `package:uninstall` commands. + +```shell +# Install a specific facade +./artisan package:install Route + +# Install all facades +./artisan package:install --all + +# Install all facades with default drivers +./artisan package:install --all --default + +# Uninstall a specific facade +./artisan package:uninstall Route +``` + +> Notice: if you are using the `./artisan package:install` command to choose the `facades` manually, you need to press `x` to select the facades you want to install, then press `Enter` to confirm. `facades` to'g'ridan-to'g'ri `Enter` tugmasini bosganingizda tanlanmaydi. From 2a96155756c0b2ae5fa50e3bd3ec2ddc0d0175a9 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:00 +0800 Subject: [PATCH 003/163] New translations request-lifecycle.md (Uzbek) [skip ci] Update translations (Uzbek) request-lifecycle.md --- .../request-lifecycle.md | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 uz_UZ/architecture-concepts/request-lifecycle.md diff --git a/uz_UZ/architecture-concepts/request-lifecycle.md b/uz_UZ/architecture-concepts/request-lifecycle.md new file mode 100644 index 000000000..5f3b90be5 --- /dev/null +++ b/uz_UZ/architecture-concepts/request-lifecycle.md @@ -0,0 +1,28 @@ +# Request Lifecycle + +[[toc]] + +## Introduction + +Using any tool in the real world feels more intuitive when you know how it works. This document aims to give you a clear, high-level look at how Goravel functions. Don’t worry if you don’t get every term right away—just aim for a basic sense of how things work, and your expertise will grow as you explore the rest of the docs. + +## Lifecycle Overview + +1. The `main.go` is the entry point of the application, it will call the `bootstrap.Boot()` function to initialize the framework, and use `app.Wait()` to keep the application running. + +2. The `bootstrap.Boot()` function will initialize a new Goravel application instance by calling `foundation.Setup()`, you can set service providers, routes, and other settings like migrations, schedules via `With*` functions here. Finally, call the `Create()` method to boot the application. + +3. In the `Create()` method, it will first load configuration, then register all service providers and other settings. Finally, boot all service providers, return the application instance. + +4. After the application is created, you can normally use all facades in this stage, but remember that your customize code should be placed before `app.Start()` in the `main.go` file. Or you can add your code into the `WithCallback` function in the `bootstrap/app.go` file to make sure your code is executed after the application is created. When running `app.Start()`, the http or grpc server will be started automatically if you have configured them. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithConfig(config.Boot). + WithCallback(func() { + // Your custom code here, all facades are available here. + }). + Create() +} +``` From 56a797842e479b6024d6e08ad443c6f9d9e44263 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:01 +0800 Subject: [PATCH 004/163] New translations service-container.md (Uzbek) [skip ci] Update translations (Uzbek) service-container.md --- .../service-container.md | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 uz_UZ/architecture-concepts/service-container.md diff --git a/uz_UZ/architecture-concepts/service-container.md b/uz_UZ/architecture-concepts/service-container.md new file mode 100644 index 000000000..8bbed269d --- /dev/null +++ b/uz_UZ/architecture-concepts/service-container.md @@ -0,0 +1,97 @@ +# Service Container + +[[toc]] + +## Introduction + +The Goravel service container is a powerful tool for managing class dependencies and performing dependency injection. It contains all the modules of Goravel, and allows you to bind your own services to container and resolve them when needed. The service container provides powerful support for third-party packages around Goravel. + +## Binding + +### Simple Bindings + +Almost all of your service container bindings will be registered within [service providers](./service-providers.md). Within a service provider, you always have access to the container via the `app` parameter, then register a binding using the `Bind` method, passing the `key` that we wish to register along with a closure that returns an instance of the class: + +```go +package route + +import ( + "github.com/goravel/framework/contracts/foundation" +) + +const Binding = "goravel.route" + +type ServiceProvider struct {} + +func (route *ServiceProvider) Register(app foundation.Application) { + app.Bind(Binding, func(app foundation.Application) (any, error) { + return NewRoute(app.MakeConfig()), nil + }) +} + +func (route *ServiceProvider) Boot(app foundation.Application) {} +``` + +As mentioned, you will typically be interacting with the container within service providers; however, if you would like to interact with the container outside of a service provider, you may do so via the `App` facade: + +```go +facades.App().Bind("key", func(app foundation.Application) (any, error) { + ... +}) +``` + +### Binding A Singleton + +The `Singleton` method binds a class or interface into the container that should only be resolved one time. Once a singleton binding is resolved, the same object instance will be returned on subsequent calls into the container: + +```go +app.Singleton(key, func(app foundation.Application) (any, error) { + return NewGin(app.MakeConfig()), nil +}) +``` + +### Binding Instances + +You may also bind an existing object instance into the container using the `Instance` method. The given instance will always be returned on subsequent calls into the container: + +```go +app.Instance(key, instance) +``` + +### Binding With Parameter + +If you need some extra parameters to construct the service provider, you can use the `BindWith` method to pass parameters to the closure: + +```go +app.BindWith(Binding, func(app foundation.Application, parameters map[string]any) (any, error) { + return NewRoute(app.MakeConfig()), nil +}) +``` + +## Resolving + +### The `Make` Method + +You may use the `Make` method to resolve a class instance from the container. The `Make` method accepts the `key` you wish to resolve: + +```go +instance, err := app.Make(key) +``` + +If you are outside of a service provider in a location of your code that does not have access to the `app` variable, you may use the `App` facade to resolve a class instance from the container: + +```go +instance, err := facades.App().Make(key) +``` + +### The `MakeWith` Method + +If some of your class's dependencies are not resolvable via the container, you may inject them by passing them as an associative array into the `MakeWith` method, corresponding to the `BindWith` binding method: + +```go +instance, err := app.MakeWith(key, map[string]any{"id": 1}) +``` + +### Other Methods + +The framework provides some convenient methods to quickly resolve various facades: `MakeArtisan`, `MakeAuth`, etc. From f0a5792831ec94a8fdf0cec3eee3ca58c1794891 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:02 +0800 Subject: [PATCH 005/163] New translations service-providers.md (Uzbek) [skip ci] Update translations (Uzbek) service-providers.md --- .../service-providers.md | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 uz_UZ/architecture-concepts/service-providers.md diff --git a/uz_UZ/architecture-concepts/service-providers.md b/uz_UZ/architecture-concepts/service-providers.md new file mode 100644 index 000000000..a1c4a3efc --- /dev/null +++ b/uz_UZ/architecture-concepts/service-providers.md @@ -0,0 +1,139 @@ +# Service Providers + +[[toc]] + +## Introduction + +The most important thing in the kernel boot operation is to load the `ServiceProvider`. All `ServiceProvider` under the application are configured in the `bootstrap/providers.go` file. + +First, the kernel will call the `Register` method of all service providers. After all service providers have been registered, the kernel will call the `Boot` method of all `ServiceProvider` again. + +The `ServiceProvider` is the key to the life cycle of Goravel. They enable the framework to contain various components, such as routing, database, queue, cache, etc. + +## Create Service Provider + +Service providers contain a `Register` and a `Boot` method. Within the `Register` method, you should only bind things into [the service container](./service-container.md). You should never attempt to register any event listeners, routes, or any other piece of functionality within the `Register` method, use the `Boot` method for that. + +```bash +./artisan make:provider YourServiceProviderName +``` + +The Artisan CLI can generate a new provider via the `make:provider` command. The new service provider will be registered automatically in the `bootstrap/providers.go::Providers()` function and the function will be called by `WithProviders`. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithProvders(Providers). + WithConfig(config.Boot). + Create() +} +``` + +## Dependency Relationship + +`ServiceProvider` provides an optional method `Relationship() binding.Relationship`, used to declare the dependency relationship, the `ServiceProvider` that sets this method will not depend on the registration order, and the `ServiceProvider` that does not set it will be registered last, for example: + +```go +type ServiceProvider struct {} + +func (r *ServiceProvider) Relationship() binding.Relationship { + return binding.Relationship{ + Bindings: []string{ + "custom", + }, + Dependencies: []string{ + binding.Config, + }, + ProvideFor: []string{ + binding.Cache, + }, + } +} + +func (r *ServiceProvider) Register(app foundation.Application) { + app.Singleton("custom", func(app foundation.Application) (any, error) { + return New() + }) +} + +func (r *ServiceProvider) Boot(app foundation.Application) {} +``` + +## Runners + +The `ServiceProvider` can also implement the `Runners` interface to run some code when the application starts. It's usually used to start/shutdown the service which is defined in the `ServiceProvider`. For example: `Route`, `Schedule`, `Queue`, etc. You don't need to start/shutdown these services with `Runners` in the `main.go` anymore, Goravel will take care of it. + +A `Runner` contains three methods: `ShouldRun()`, `Run()`, and `Shutdown()`. + +```go +type Runner interface { + // ShouldRun determines whether the runner should be executed. + ShouldRun() bool + // Run starts the runner. + Run() error + // Shutdown gracefully stops the runner. + Shutdown() error +} +``` + +There is an example of a `RouteRunner` defined in the `ServiceProvider` to start and shutdown the `Route` service. + +```go +type ServiceProvider struct {} + +func (r *ServiceProvider) Register(app foundation.Application) {} + +func (r *ServiceProvider) Boot(app foundation.Application) {} + +func (r *ServiceProvider) Runners(app foundation.Application) []foundation.Runner { + return []foundation.Runner{NewRouteRunner(app.MakeConfig(), app.MakeRoute())} +} +``` + +```go +package route + +import ( + "github.com/goravel/framework/contracts/config" + "github.com/goravel/framework/contracts/route" +) + +type RouteRunner struct { + config config.Config + route route.Route +} + +func NewRouteRunner(config config.Config, route route.Route) *RouteRunner { + return &RouteRunner{ + config: config, + route: route, + } +} + +func (r *RouteRunner) ShouldRun() bool { + return r.route != nil && r.config.GetString("http.default") != "" +} + +func (r *RouteRunner) Run() error { + return r.route.Run() +} + +func (r *RouteRunner) Shutdown() error { + return r.route.Shutdown() +} +``` + +You can register your own `Runner` in the `bootstrap/app.go::WithRunners` function to run some code when the application starts. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithConfig(config.Boot). + WithRunners(func() []foundation.Runner{ + return []foundation.Runner{ + NewYourCustomRunner(), + } + }). + Create() +} +``` From b1aac2469f3534d58d208df0d1e27a86a7df0aa1 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:03 +0800 Subject: [PATCH 006/163] New translations getting-started.md (Uzbek) [skip ci] Update translations (Uzbek) getting-started.md --- uz_UZ/database/getting-started.md | 184 ++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 uz_UZ/database/getting-started.md diff --git a/uz_UZ/database/getting-started.md b/uz_UZ/database/getting-started.md new file mode 100644 index 000000000..f4bc83ad7 --- /dev/null +++ b/uz_UZ/database/getting-started.md @@ -0,0 +1,184 @@ +# Getting Started + +[[toc]] + +## Introduction + +Almost all applications need to interact with databases, so Goravel provides a very simple and easy-to-use database interaction. Developers can use native SQL, query builder, and [Orm](../orm/getting-started) to interact with databases. Currently, Goravel provides official support for the following four databases: + +| Database | Driver | +| ---------- | ------------------------------------------------------------------------------------ | +| PostgreSQL | [github.com/goravel/postgres](https://github.com/goravel/postgres) | +| MySQL | [github.com/goravel/mysql](https://github.com/goravel/mysql) | +| SQL Server | [github.com/goravel/sqlserver](https://github.com/goravel/sqlserver) | +| SQLite | [github.com/goravel/sqlite](https://github.com/goravel/sqlite) | + +## Configuration + +The database configuration file is `config/database.go`. You can configure all database connections in this file and specify the default database connection. Most of the configuration in this file is based on the project's environment variables. + +### Connection Pool + +You can configure the database connection pool in the configuration file to improve the concurrency performance by properly configuring the connection pool parameters: + +| Configuration Key | Description | +| -------------------------------------------------------------------------------- | ---------------------------- | +| pool.max_idle_conns | Maximum idle connections | +| pool.max_open_conns | Maximum connections | +| pool.conn_max_idletime | Connection maximum idle time | +| pool.conn_max_lifetime | Connection maximum lifetime | + +### Read-Write Splitting + +Sometimes you may want to use a database connection to execute `SELECT` statements, while `INSERT`, `UPDATE`, and `DELETE` statements are executed by another database connection. In Goravel, it is easy to implement read-write splitting. + +```go +import "github.com/goravel/framework/contracts/database" + +// config/database.go +"connections": map[string]any{ + "mysql": map[string]any{ + "driver": "mysql", + "read": []database.Config{ + {Host: "192.168.1.1", Port: 3306, Database: "forge", Username: "root", Password: "123123"}, + }, + "write": []database.Config{ + {Host: "192.168.1.2", Port: 3306, Database: "forge", Username: "root", Password: "123123"}, + }, + "host": config.Env("DB_HOST", "127.0.0.1"), + "port": config.Env("DB_PORT", 3306), + "database": config.Env("DB_DATABASE", "forge"), + "username": config.Env("DB_USERNAME", ""), + "password": config.Env("DB_PASSWORD", ""), + "charset": "utf8mb4", + }, +} +``` + +We have added two keys, `read` and `write`, in the database configuration. `192.168.1.1` will be used as the "read" connection host, and `192.168.1.2` will be used as the "write" connection host. These two connections will share the configurations in the `mysql` array, such as the database prefix and character encoding. If there are multiple values in the `read` or `write` arrays, Goravel will randomly select the database host for each connection. + +## Running Native SQL Queries + +After configuring the database connection, you can use `facades.DB()` to run queries. `facades.DB()` provides various methods for running queries: `Select`, `Insert`, `Update`, `Delete`, and `Statement`. + +### Select + +Use the `facades.DB().Select()` method to execute basic queries: + +```go +// Get multiple records +var products []Product +err := facades.DB().Select(&products, "SELECT * FROM products") + +// Get a single record +var product Product +err := facades.DB().Select(&product, "SELECT * FROM products WHERE id = ?", 1) +``` + +> Note: Different database drivers require different placeholders. For example, the `?` placeholder is used for MySQL, while the `@` placeholder is used for PostgreSQL. + +### Insert + +Use the `facades.DB().Insert()` method to execute insertion statements: + +```go +result, err := facades.DB().Insert("insert into users (name, email) values (?, ?)", "Goravel", "goravel@example.com") +``` + +### Update + +Use the `facades.DB().Update()` method to execute update statements: + +```go +result, err := facades.DB().Update("update users set name = ? where id = ?", "Goravel", 1) +``` + +### Delete + +Use the `facades.DB().Delete()` method to execute delete statements: + +```go +result, err := facades.DB().Delete("delete from users where id = ?", 1) +``` + +### Statement + +Use the `facades.DB().Statement()` method to execute general statements: + +```go +err := facades.DB().Statement("drop table users") +``` + +### Using Multiple Database Connections + +If you define multiple database connections in the configuration file, you can specify the connection to use by calling the `facades.DB().Connection()` method: + +```go +var user User +err := facades.DB().Connection("postgres").Select(&user, "select * from users where id = ?", 1) +``` + +## Database Transactions + +You can use the `facades.DB().Transaction()` method to execute a series of operations in a database transaction. If an exception is thrown in the transaction closure, the transaction will be automatically rolled back. If the closure executes successfully, the transaction will be automatically committed: + +```go +import "github.com/goravel/framework/contracts/database/db" + +err := facades.DB().Transaction(func(tx db.Tx) error { + _, err := tx.Table("products").Insert(Product{Name: "transaction product1"}) + + return err +}) +``` + +### Manually Using Transactions + +If you want to manually control the start, commit, and rollback of a transaction, you can use the `Begin`、`Commit` and `Rollback` methods: + +```go +tx, err := facades.DB().BeginTransaction() +if err != nil { + return err +} + +_, err = tx.Insert("insert into users (name) values (?)", "Goravel") +if err != nil { + tx.Rollback() + return err +} + +err = tx.Commit() +if err != nil { + return err +} +``` + +## Checking Databases + +### Database Overview + +Goravel provides several Artisan commands to help you understand the structure of the database. + +You can use the `db:show` command to view all tables in the database. + +```bash +./artisan db:show +./artisan db:show --database=postgres +``` + +You can also use the `db:table` command to view the structure of a specific table. + +```bash +./artisan db:table +./artisan db:table --database=postgres +``` + +### Table Overview + +If you want to get an overview of a single table in the database, you can execute the `db:table` Artisan command. This command provides an overview of a database table, including its columns, types, attributes, keys, and indexes: + +```bash +./artisan db:table users +./artisan db:table users --database=postgres +``` From b8a5cc2314d7941e8a086c493af99349bed61dfc Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:04 +0800 Subject: [PATCH 007/163] New translations migrations.md (Uzbek) [skip ci] Update translations (Uzbek) migrations.md --- uz_UZ/database/migrations.md | 418 +++++++++++++++++++++++++++++++++++ 1 file changed, 418 insertions(+) create mode 100644 uz_UZ/database/migrations.md diff --git a/uz_UZ/database/migrations.md b/uz_UZ/database/migrations.md new file mode 100644 index 000000000..d3d9a8969 --- /dev/null +++ b/uz_UZ/database/migrations.md @@ -0,0 +1,418 @@ +# Migrations + +[[toc]] + +## Introduction + +When multiple people collaborate to develop applications, it's crucial to have a standardized database structure for synchronization. Without this, there could be chaos as everyone's individual data won't match up. Database migration is the solution to this problem. The database structure is version-controlled to ensure its consistency within all developers. + +## Configuration + +The database migration files are stored in the `database/migrations` directory. You can configure the database connection information in the `config/database.go` file. + +```go +"migrations": map[string]any{ + // You can cumstomize the table name of migrations + "table": "migrations", +}, +``` + +## Create Migrations + +Use the `make:migration` command to create the migration: + +```shell +./artisan make:migration +./artisan make:migration create_users_table +``` + +This command will generate migration files in the `database/migrations` directory. Each migration file will begin with a timestamp, which Goravel will use to determine the execution order of the migration files. + +You can also create a migration for a specific model by using the `-m` or `--model` option: + +```shell +./artisan make:migration create_users_table -m User +``` + +The model should be registered in the `bootstrap/app.go` file before running the command. This command will generate a migration file based on the structure defined in the `User` model. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithConfig(config.Boot). + WithCallback(func() { + facades.Schema().Extend(schema.Extension{ + Models: []any{models.User{}}, + }) + }). + Create() +} +``` + +### Quickly Create + +Use `create_users_table` to automatically generate a table containing the infrastructure of `users`: + +``` +^create_(\w+)_table$ +^create_(\w+)$ +``` + +Use `add_avatar_to_users_table` to automatically generate a structure for adding fields to the `users` table: + +``` +_(to|from|in)_(\w+)_table$ +_(to|from|in)_(\w+)$ +``` + +If the above conditions are not matched, the framework will generate an empty migration file. + +## Migration Structure + +### Go Language Migration + +The migration struct contains two methods: `Up` and `Down`. The `Up` method is used to add new tables, columns, or indexes to the database, while the `Down` method is used to undo the operations performed by the `Up` method. In these two methods, you can use `facades.Schema()` to create and operate database tables. For available methods, see the [documentation](#tables). The following migration will create a `users` table: + +```go +package migrations + +import ( + "github.com/goravel/framework/contracts/database/schema" + + "goravel/app/facades" +) + +type M20241207095921CreateUsersTable struct { +} + +// Signature The unique signature for the migration. +func (r *M20241207095921CreateUsersTable) Signature() string { + return "20241207095921_create_users_table" +} + +// Up Run the migrations. +func (r *M20241207095921CreateUsersTable) Up() error { + if !facades.Schema().HasTable("users") { + return facades.Schema().Create("users", func(table schema.Blueprint) { + table.ID() + table.String("name").Nullable() + table.String("email").Nullable() + table.Timestamps() + }) + } + + return nil +} + +// Down Reverse the migrations. +func (r *M20241207095921CreateUsersTable) Down() error { + return facades.Schema().DropIfExists("users") +} +``` + +#### Set Migration Connection + +If the migration will interact with a database connection other than the application's default database connection, you should use the migration's `Connection` method: + +```go +func (r *M20241207095921CreateUsersTable) Connection() string { + return "connection-name" +} +``` + +## Register Migrations + +A new migration created by `make:migration` will be registered automatically in the `bootstrap/migrations.go::Migrations()` function and the function will be called by `WithMigrations`. You need register the rule manually if you create the migration file by yourself. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithMigrations(Migrations). + WithConfig(config.Boot). + Create() +} +``` + +## Run Migrations + +To run all of your outstanding migrations, execute the `migrate` Artisan command: + +```shell +./artisan migrate +``` + +If you would like to see which migrations have run thus far, you may use the `migrate:status` Artisan command: + +```shell +./artisan migrate:status +``` + +## Rolling Back Migrations + +To roll back the latest migration batch, use the `rollback` Artisan command: + +```shell +./artisan migrate:rollback +``` + +If you want to roll back multiple migration batches, you can specify the `batch` option, the number indicates which batch to roll back: + +```shell +./artisan migrate:rollback --batch=2 +``` + +You may roll back a limited number of migrations by providing the `step` option to the `rollback` command. For example, the following command will roll back the last five migrations: + +```shell +./artisan migrate:rollback --step=5 +``` + +The `migrate:reset` command will roll back all of your application's migrations: + +```shell +./artisan migrate:reset +``` + +### Roll Back & Migrate Using A Single Command + +The `migrate:refresh` command will roll back all of your migrations and then execute the `migrate` command. This command effectively re-creates your entire database: + +```shell +./artisan migrate:refresh +``` + +You may roll back and re-migrate a limited number of migrations by providing the `step` option to the `refresh` command. For example, the following command will roll back and re-migrate the last five migrations: + +```shell +./artisan migrate:refresh --step=5 +``` + +### Drop All Tables & Migrate + +The `migrate:fresh` command will drop all tables from the database and then execute the `migrate` command: + +```shell +./artisan migrate:fresh +``` + +## Tables + +### Create Table + +```go +facades.Schema().Create("users", func(table schema.Blueprint) { + table.ID() + table.String("name").Nullable() + table.String("email").Nullable() + table.Timestamps() +}) +``` + +### Check If Table / Column Exists + +```go +if facades.Schema().HasTable("users") {} +if facades.Schema().HasColumn("users", "email") {} +if facades.Schema().HasColumns("users", []string{"name", "email"}) {} +if facades.Schema().HasIndex("users", "email_unique") {} +``` + +### Database Connection + +```go +facades.Schema().Connection("sqlite").Create("users", func(table schema.Blueprint) { + table.ID() +}) +``` + +### Update Table + +```go +facades.Schema().Table("users", func(table schema.Blueprint) { + table.String("name").Nullable() +}) +``` + +### Rename Column + +```go +facades.Schema().Table("users", func(table schema.Blueprint) { + table.RenameColumn("old_name", "new_name") +}) +``` + +### Add Table Comment + +```go +facades.Schema().Table("users", func(table schema.Blueprint) { + table.Comment("user table") +}) +``` + +### Rename / Drop Table + +```go +facades.Schema().Rename("users", "new_users") +facades.Schema().Drop("users") +facades.Schema().DropIfExists("users") + +``` + +## Columns + +### Available Column Types + +#### Boolean Types + +Boolean + +#### String & Text Types + +Char, Json, LongText, MediumText, String, Text, LongText, TinyText, Uuid, Ulid + +#### Numeric Types + +BigIncrements, BigInteger, Decimal, Double, Float, [ID](#id), Increments, Integer, IntegerIncrements, MediumIncrements, MediumInteger, SmallIncrements, SmallInteger, TinyIncrements, TinyInteger, UnsignedBigInteger, UnsignedInteger, UnsignedMediumInteger, UnsignedSmallInteger, UnsignedTinyInteger + +#### Date & Time Types + +Date, DateTime, DateTimeTz, [SoftDeletes](#softdeletes), SoftDeletesTz, Time, TimeTz, Timestamp, TimestampTz, Timestamps, TimestampsTz + +#### Other Types + +[Enum](#enum), Morphs, NullableMorphs, NumericMorphs, UuidMorphs, UlidMorphs + +#### Enum + +Create an `Enum` field that can be stored in `Mysql` according to the type in `[]any`, but in `Postgres`, `Sqlite`, and `Sqlserver` databases, it is a `String` type. + +```go +table.Enum("difficulty", []any{"easy", "hard"}) +table.Enum("num", []any{1, 2}) +``` + +#### ID + +The `ID` method is an alias for the `BigIncrements` method. By default, this method will create an `id` column; however, if you would like to assign a different name to the column, you may pass the column name: + +```go +table.ID() +table.ID("user_id") +``` + +#### SoftDeletes + +The `SoftDeletes` method adds a nullable `deleted_at` `TIMESTAMP` column. This column is intended to store the `deleted_at` timestamp required for the Orm "soft delete" feature: + +```go +table.SoftDeletes() +``` + +#### Custom column + +If you are using column types that framework does not support yet, you can use the `Column` method to customize the field type: + +```go +table.Column("geometry", "geometry") +``` + +### Column Modifiers + +In addition to the column types listed above, when adding a column to a database table, you can also add "modifiers" to the column. For example, to allow a column to be "nullable," you can use the `Nullable` method: + +```go +facades.Schema().Table("users", func(table schema.Blueprint) { + table.String("name").Nullable() +}) +``` + +The following table contains all available column modifiers: + +| Modified | Description | +| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `.Always()` | The value of this column is always generated by the database system, and users cannot directly insert or modify it (only PostgreSQL) | +| `.AutoIncrement()` | Sets an integer column as auto-incrementing (primary key) | +| `.After("column")` | Sets the column after the specified column (MySQL only) | +| `.Comment("my comment")` | Adds a comment to the column (MySQL / PostgreSQL) | +| `.Change()` | Modify the column structure (MySQL / PostgreSQL / Sqlserver) | +| `.Default(value)` | Sets the default value for the column | +| `.First()` | Sets the column as the first column (MySQL only) | +| `.GeneratedAs()` | Sets the value of the column to be generated by the database system (only PostgreSQL) | +| `.Nullable()` | Allows NULL values to be inserted into the column | +| `.Unsigned()` | Sets an integer column as UNSIGNED (MySQL only) | +| `.UseCurrent()` | Sets a timestamp column to use CURRENT_TIMESTAMP as the default value | +| `.UseCurrentOnUpdate()` | Sets a timestamp column to use CURRENT_TIMESTAMP when the record is updated (MySQL only) | + +### Drop Column + +```go +facades.Schema().Table("users", func(table schema.Blueprint) { + table.DropColumn("name") + table.DropColumn("name", "age") +}) +``` + +## Indexes + +### Create Index + +```go +facades.Schema().Table("users", func(table schema.Blueprint) { + // Add primary key + table.Primary("id") + // Add composite primary key + table.Primary("id", "name") + + // Add unique index + table.Unique("name") + table.Unique("name", "age") + + // Add normal index + table.Index("name") + table.Index("name", "age") + + // Add fulltext index + table.FullText("name") + table.FullText("name", "age") +}) +``` + +### Rename Index + +```go +facades.Schema().Table("users", func(table schema.Blueprint) { + table.RenameIndex("users_name_index", "users_name") +}) +``` + +### Drop Index + +```go +facades.Schema().Table("users", func(table schema.Blueprint) { + table.DropPrimary("id") + table.DropUnique("name") + table.DropUniqueByName("name_unique") + table.DropIndex("name") + table.DropIndexByName("name_index") + table.DropFullText("name") + table.DropFullTextByName("name_fulltext") +}) +``` + +### Create Foreign Key + +```go +facades.Schema().Table("posts", func(table schema.Blueprint) { + table.UnsignedBigInteger("user_id") + table.Foreign("user_id").References("id").On("users") +}) +``` + +### Drop Foreign Key + +```go +facades.Schema().Table("users", func(table schema.Blueprint) { + table.DropForeign("user_id") + table.DropForeignByName("user_id_foreign") +}) +``` From da57267b2497daf7fd12182a3ef553887edc7d04 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:05 +0800 Subject: [PATCH 008/163] New translations queries.md (Uzbek) [skip ci] Update translations (Uzbek) queries.md --- uz_UZ/database/queries.md | 667 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 667 insertions(+) create mode 100644 uz_UZ/database/queries.md diff --git a/uz_UZ/database/queries.md b/uz_UZ/database/queries.md new file mode 100644 index 000000000..87343a12b --- /dev/null +++ b/uz_UZ/database/queries.md @@ -0,0 +1,667 @@ +# Query Builder + +[[toc]] + +## Introduction + +The database query builder provides a convenient interface to create and execute database queries. It can be used to perform most database operations in your application and works with all supported database systems. + +Query builder uses parameter binding to protect your application from SQL injection. You don't need to clean or escape strings passed to the query builder. + +## Running Queries + +Framework provides various query methods, you can query, create, update and delete data in the database. Note that when you want to bind data to `struct` or [model](../orm/getting-started.md#model-definition), you need to add the `db` tag to the field: + +```go +type User struct { + ID string `db:"id"` + Name string `db:"name"` +} + +type User struct { + orm.BaseModel + orm.NullableSoftDeletes + Name string `db:"name"` +} +``` + +### Retrieving All Rows + +You can use the `facades.DB()` provided `table` method to start a query. The `table` method returns a chainable query builder instance for the specified table, allowing you to chain more constraints, and finally use the `Get` method to retrieve the query results: + +```go +var users []User +err := facades.DB().Table("users").Get(&users) +``` + +### Retrieving a Single Row or Column + +If you only need to retrieve a single row of data from the database table, you can use the `First` method. + +```go +var user User +err := facades.DB().Table("users").Where("id", 1).First(&user) +``` + +You can use the `Value` method to retrieve the value of a single column: + +```go +var name string +err := facades.DB().Table("users").Where("id", 1).Value("name", &name) +``` + +You can use the `Find` method to retrieve a single row of data by passing the `id`: + +```go +var user User +err := facades.DB().Table("users").Find(&user, 1) + +// You can also pass a collection of `id` to retrieve multiple rows of data +var users []User +err := facades.DB().Table("users").Find(&users, []int{1, 2, 3}) + +// Find defaults the table primary key to `id`, if the table primary key is not `id`, you can pass the `id` field name +var user User +err := facades.DB().Table("users").Find(&users, "uuid", "1") +``` + +You can use the `FindOrFail` or `FirstOrFail` method, if the record is not found, it will throw a `sql.ErrNoRows` error: + +```go +var user User +err := facades.DB().Table("users").FindOrFail(&user, 1) +``` + +You can use the `FindOr` or `FirstOr` method, if the record is not found, it will execute the closure function: + +```go +var user *User +err = facades.DB().Table("users").Where("name", "John").FirstOr(&user, func() error { + return errors.New("no rows") +}) +``` + +### Retrieving a Single Column Value + +If you want to retrieve a list of records containing a single column value, you can use the `Pluck` method: + +```go +var emails []string +err := facades.DB().Table("users").Pluck("email", &emails) +``` + +### Traversing Results + +You can use the `Each` method to traverse all results: + +```go +var products []Product +err := facades.DB().Table("products").Each(func(rows []db.Row) error { + for _, row := range rows { + var product Product + if err := row.Scan(&product); err != nil { + return err + } + + products = append(products, product) + } + + return nil +}) +``` + +### Chunking Results + +If you need to process thousands of database records, consider using the `Chunk` method. This method retrieves a small chunk of results at a time and passes each chunk to a closure function for processing: + +```go +var products []Product +err := facades.DB().Table("products").Chunk(2, func(rows []db.Row) error { + for _, row := range rows { + var product Product + if err := row.Scan(&product); err != nil { + return err + } + + products = append(products, product) + } + + return nil +}) +``` + +> Note: When modifying records in the Chunk callback, it may result in records not being included in the chunked results. + +### Cursor + +A cursor can be used to process large amounts of data without loading all data into memory at once. It processes data one by one instead of loading all data at once. + +```go +rows, err := facades.DB().Table("products").Cursor() + +var products []Product +for row := range rows { + var product Product + if err := row.Scan(&product); err != nil { + return err + } + + products = append(products, product) +} +``` + +### Aggregates + +The query builder provides aggregate methods: `Count`, `Sum`, `Avg`, `Min`, `Max`. + +```go +count, err := facades.DB().Table("users").Count() + +var sum int +err := facades.DB().Table("users").Sum("age", &sum) + +var avg float64 +err := facades.DB().Table("users").Avg("age", &avg) + +var min int +err := facades.DB().Table("users").Min("age", &min) + +var max int +err := facades.DB().Table("users").Max("age", &max) +``` + +### Checking if a Record Exists + +You can use the `Exists` and `DoesntExist` methods to determine if the result of a query condition exists: + +```go +exists, err := facades.DB().Table("users").Where("votes > ?", 100).Exists() + +exists, err := facades.DB().Table("users").Where("votes > ?", 100).DoesntExist() +``` + +### Pagination + +You can use the `Paginate` method to paginate the query results: + +```go +var ( + users []User + total int64 +) + +err := facades.DB().Table("users").Where("name", "John").Paginate(1, 10, &users, &total) +``` + +## Select + +You may not always want to retrieve all columns from a database table. Use the `Select` method to customize a "select" query statement to query the specified fields: + +```go +var users []User +err := facades.DB().Table("users").Select("name", "email as user_email").Get(&users) +``` + +The `Distinct` method will force the query to return unique results: + +```go +var users []User +err := facades.DB().Table("users").Distinct().Select("name").Get(&users) +``` + +## Raw Expressions + +Sometimes you may need to use raw expressions in your queries. You can use the `db.Raw` method to create a raw expression: + +```go +import "github.com/goravel/framework/database/db" + +res, err := facades.DB().Model(&user).Update("age", db.Raw("age - ?", 1)) +``` + +## Select + +### Specifying a Select Clause + +Of course, you may not always want to retrieve all columns from a database table. Use the `Select` method to specify a custom select clause for your query: + +```go +// Select specific fields +err := facades.DB().Select("name", "age").Get(&users) + +// Use a subquery +err := facades.DB().Select("name", db.Raw("(SELECT COUNT(*) FROM posts WHERE users.id = posts.user_id) as post_count")).Get(&users) +``` + +### Distinct + +The `Distinct` method will force the query to return unique results: + +```go +var users []models.User +err := facades.DB().Distinct("name").Find(&users) +``` + +## Raw Methods + +### WhereRaw / OrWhereRaw + +The `WhereRaw` and `OrWhereRaw` methods can be used to inject raw "where" clauses into your query. These methods accept an optional binding array as their second parameter: + +```go +var users []User + +err := facades.DB().WhereRaw("age = ? or age = ?", []any{25, 30}).Get(&users) + +err := facades.DB().OrWhereRaw("age = ? or age = ?", []any{25, 30}).Get(&users) +``` + +### OrderByRaw + +The `OrderByRaw` method can be used to set a raw string as the value of the "order by" clause: + +```go +var users []User + +err := facades.DB().OrderByRaw("age DESC, id ASC").Get(&users) +``` + +## Joins + +### Inner Join + +The query builder can be used to write join statements. To execute a basic SQL "inner join", you can use the `Join` method on the query builder instance: + +```go +var users []User + +err := facades.DB().Table("users").Join("posts as p ON users.id = p.user_id AND p.id = ?", 1).Where("age", 25).Get(&users) +``` + +### Left Join / Right Join + +If you want to execute a "left join" or "right join", you can use the `LeftJoin` or `RightJoin` methods: + +```go +var users []User + +err := facades.DB().Table("users").LeftJoin("posts as p ON users.id = p.user_id AND p.id = ?", 1).Where("age", 25).Get(&users) + +err = facades.DB().Table("users").RightJoin("posts as p ON users.id = p.user_id AND p.id = ?", 1).Where("age", 25).Get(&users) +``` + +### Cross Join + +The `CrossJoin` method can be used to execute a "cross join": + +```go +var users []User + +err := facades.DB().Table("users").CrossJoin("posts as p ON users.id = p.user_id AND p.id = ?", 1).Where("age", 25).Get(&users) +``` + +## Basic Where Clauses + +### Where / OrWhere + +You can use the `Where` method on the query builder instance to add where clauses to the query. + +```go +import "github.com/goravel/framework/contracts/database/db" + +var users []User + +err := facades.DB().Where("votes", 100).Get(&users) + +err := facades.DB().Where("votes >= ?", 100).Get(&users) + +err := facades.DB().Where("votes LIKE ?", "%goravel%").Get(&users) + +err := facades.DB().Where("votes", []int{1, 2, 3}).Get(&users) + +err := facades.DB().Where(func(query db.Query) db.Query { + return query.Where("age", []int{25, 30}).Where("name", "Tom") +}).OrWhere("name", "John").Get(&users) +``` + +### WhereNot / OrWhereNot + +The `WhereNot` and `OrWhereNot` methods can be used to negate a given set of query conditions. + +```go +import "github.com/goravel/framework/contracts/database/db" + +var users []User + +err := facades.DB().WhereNot("votes", 100).Get(&users) + +err := facades.DB().WhereNot("votes >= ?", 100).Get(&users) + +err := facades.DB().WhereNot("votes LIKE ?", "%goravel%").Get(&users) + +err := facades.DB().WhereNot("votes", []int{1, 2, 3}).Get(&users) + +err := facades.DB().WhereNot(func(query db.Query) db.Query { + return query.Where("age", []int{25, 30}).Where("name", "Tom") +}).OrWhereNot("name", "John").Get(&users) +``` + +### WhereExists / WhereNotExists + +The `WhereExists` method allows you to write exists SQL clauses: + +```go +var users []User + +err := facades.DB().Table("users").Where("name", "John").WhereExists(func() db.Query { + return facades.DB().Table("posts").WhereColumn("posts.user_id", "users.id") +}).Get(&users) +``` + +### WhereAll / WhereAny / WhereNone + +```go +var products []Product +facades.DB().Table("products").WhereAll([]string{"weight", "height"}, "=", 200).Find(&products) +// SQL: SELECT * FROM products WHERE weight = ? AND height = ? + +var users []User +facades.DB().Table("users").WhereAny([]string{"name", "email"}, "=", "John").Find(&users) +// SQL: SELECT * FROM users WHERE (name = ? OR email = ?) + +var products []Product +facades.DB().Table("products").WhereNone([]string{"age", "score"}, ">", 18).Find(&products) +// SQL: SELECT * FROM products WHERE NOT (age > ?) AND NOT (score > ?) +``` + +### Other Where Clauses + +**WhereBetween / OrWhereBetween** + +The `WhereBetween` method verifies that a field value is between two given values: + +```go +facades.DB().Table("users").WhereBetween("votes", 1, 100) +``` + +**WhereNotBetween / OrWhereNotBetween** + +The `WhereNotBetween` method verifies that a field value is not between two given values: + +```go +facades.DB().Table("users").WhereNotBetween("votes", 1, 100) +``` + +**WhereIn / WhereNotIn / OrWhereIn / OrWhereNotIn** + +The `WhereIn` method verifies that a field value must exist in the specified array: + +```go +facades.DB().Table("users").WhereIn("id", []any{1, 2, 3}) +``` + +**WhereNull / WhereNotNull / OrWhereNull / OrWhereNotNull** + +The `WhereNull` method verifies that a specified field must be `NULL`: + +```go +facades.DB().Table("users").WhereNull("updated_at") +``` + +**WhereLike / WhereNotLike / OrWhereLike / OrWhereNotLike** + +The `WhereLike` method verifies that a field value contains a given value: + +```go +facades.DB().Table("users").WhereLike("name", "%goravel%") +``` + +**WhereColumn / OrWhereColumn** + +The `WhereColumn` method verifies that two fields are equal: + +```go +facades.DB().Table("users").WhereColumn("first_name", "last_name") +``` + +### Logical Grouping + +Sometimes you may need to group several "where" clauses within parentheses to achieve the logical grouping required by your query. + +```go +facades.DB().Table("users").Where("age", 25).Where(func(query db.Query) db.Query { + return query.Where("votes", 100).OrWhere("votes", 200) +}) +``` + +## Ordering, Grouping, Limit & Offset + +### Ordering + +**OrderBy / OrderByDesc** + +```go +facades.DB().OrderBy("name") + +facades.DB().OrderByDesc("name") +``` + +**Latest** + +The `Latest` method makes it easy to sort results by date. By default, results will be sorted by the `created_at` column: + +```go +err := facades.DB().Table("users").Latest().First(&user) + +err := facades.DB().Table("users").Latest("updated_at").First(&user) +``` + +**InRandomOrder** + +The `InRandomOrder` method is used to sort results randomly: + +```go +err := facades.DB().Table("users").InRandomOrder().First(&user) +``` + +### Grouping + +The `GroupBy` and `Having` methods can be used to group results: + +```go +err := facades.DB().Table("users").Where("age", 25).GroupBy("name").Having("name = ?", "John").OrderBy("name").Get(&users) +``` + +### Limiting and Offset + +You can use the `Limit` and `Offset` methods to limit the number of results, or skip a specified number of results in the query: + +```go +err := facades.DB().Table("users").Offset(10).Limit(5).Get(&users) +``` + +## Conditional Clauses + +Sometimes you may want a clause to only execute when a given condition is true. For example, you may only want to apply a where clause when a given value exists in the request. You can accomplish this by using the `When` method: + +```go +import "github.com/goravel/framework/contracts/database/db" + +err := facades.DB().Table("users").When(1 == 1, func(query db.Query) db.Query { + return query.Where("age", 25) +}).First(&user) +``` + +You can also pass another closure as the third parameter to the `When` method. This closure will execute if the first parameter results in false: + +```go +err := facades.DB().Table("users").When(1 != 1, func(query db.Query) db.Query { + return query.OrderBy("name") +}, func(query db.Query) db.Query { + return query.OrderBy("id") +}).First(&user) +``` + +## Insert + +The query builder provides the `Insert` method for inserting records into the database: + +```go +// Insert by struct +result, err := facades.DB().Table("products").Insert(Product{ + Name: "goravel", +}) + +// Insert by slice struct +result, err := facades.DB().Table("products").Insert([]Product{ + { + Name: "goravel", + }, + { + Name: "go", + }, +}) + +// Insert by map +result, err := facades.DB().Table("products").Insert(map[string]any{ + "name": "goravel", + "created_at": time.Now(), + "updated_at": time.Now(), +}) + +// Insert by slice map +result, err := facades.DB().Table("products").Insert([]map[string]any{ + { + "name": "goravel", + "created_at": time.Now(), + "updated_at": time.Now(), + }, + { + "name": "go", + "created_at": time.Now(), + "updated_at": time.Now(), + }, +}) +``` + +### Auto Increment ID + +If the table's primary key is auto increment, you can use the `LastInsertID` method to get the auto increment ID, only supported for `mysql` and `sqlite` databases: + +```go +id, err := facades.DB().Table("products").InsertGetID(Product{ + Name: "goravel", +}) +``` + +## Update + +The query builder provides the `Update` method for updating existing records in the database: + +```go +// Update by field name +result, err := facades.DB().Table("products").Where("id", 1).Update("phone", "1234567890") + +// Update by struct +result, err := facades.DB().Table("products").Where("id", 1).Update(Product{ + Name: "goravel", +}) + +// Update by map +result, err := facades.DB().Table("products").Where("id", 1).Update(map[string]any{ + "name": "goravel", + "created_at": time.Now(), + "updated_at": time.Now(), +}) +``` + +### Update JSON fields + +```go +result, err := facades.DB().Table("users").Where("id", 1).Update("options->enabled", true) +result, err := facades.DB().Table("users").Where("id", 1).Update("options->languages[0]", "en") +result, err := facades.DB().Table("users").Where("id", 1).Update("options->languages", []string{"en", "de"}) +result, err := facades.DB().Table("users").Where("id", 1).Update(map[string]any{ + "preferences->dining->meal": "salad", + "options->languages[0]": "en", + "options->enabled": true, +}) +``` + +### Update or Insert + +Sometimes you may want to update a record in the database, but if the specified record does not exist, create it. This can be done using the `UpdateOrInsert` method. The `UpdateOrInsert` method accepts two parameters: a condition for finding the record, and a key-value pair containing the values to update the record with. + +The `UpdateOrInsert` method will attempt to locate a matching database record using the column names and values from the first parameter. If a record exists, its values will be updated using the second parameter. If no matching record is found, a record will be created and its values will be merged from the two parameters: + +```go +// use struct +result, err := facades.DB().Table("users").Where("id", 1).UpdateOrInsert(TestUser{ + Email: "john@example.com", +}, TestUser{ + Phone: "1234567890", +}) + +// use map +result, err := facades.DB().Table("users").Where("id", 1).UpdateOrInsert(map[string]any{ + "email": "john@example.com", +}, map[string]any{ + "phone": "1234567890", +}) +``` + +### Increment and Decrement + +The `Increment` and `Decrement` methods can be used to increment or decrement the value of a specified field: + +```go +err := facades.DB().Table("users").Where("id", 1).Increment("votes") + +err := facades.DB().Table("users").Where("id", 1).Increment("votes", 2) + +err := facades.DB().Table("users").Where("id", 1).Decrement("votes") + +err := facades.DB().Table("users").Where("id", 1).Decrement("votes", 2) +``` + +## Delete + +The query builder also includes some functions that can help you implement "pessimistic locking" in your `select` statements: + +```go +result, err := facades.DB().Table("users").Where("id", 1).Delete() +``` + +## Pessimistic Locking + +The query builder also includes some functions that can help you implement "pessimistic locking" in your `select` statements: + +To use a "shared lock", you may use the `SharedLock` method. A shared lock prevents the selected rows from being modified until the transaction is committed: + +```go +err := facades.DB().Table("users").Where("votes > ?", 100).SharedLock().Get(&users) +``` + +You can also use the `LockForUpdate` method. Using the "update" lock can prevent rows from being modified or selected by other shared locks: + +```go +err := facades.DB().Table("users").Where("votes > ?", 100).LockForUpdate().Get(&users) +``` + +## Debugging + +You can use the `ToSQL` and `ToRawSql` methods to get the current query binding and SQL. + +With placeholder SQL: + +```go +err := facades.DB().Table("users").Where("id", 1).ToSql().Get(models.User{}) +``` + +With bound values SQL: + +```go +err := facades.DB().Table("users").Where("id", 1).ToRawSql().Get(models.User{}) +``` + +The methods that can be called after `ToSql` and `ToRawSql`: `Count`, `Insert`, `Delete`, `First`, `Get`, `Pluck`, `Update`. From d942222b28544271cdf35c86a3212e65060dc750 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:06 +0800 Subject: [PATCH 009/163] New translations seeding.md (Uzbek) [skip ci] Update translations (Uzbek) seeding.md --- uz_UZ/database/seeding.md | 111 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 uz_UZ/database/seeding.md diff --git a/uz_UZ/database/seeding.md b/uz_UZ/database/seeding.md new file mode 100644 index 000000000..8531ee9bf --- /dev/null +++ b/uz_UZ/database/seeding.md @@ -0,0 +1,111 @@ +# Database: Seeding + +[[toc]] + +## Introduction + +Goravel includes the ability to seed your database with data using seed struct. All seed structs are stored in the `database/seeders` directory. By default, a `DatabaseSeeder` struct is defined for you. + +## Writing Seeders + +To generate a seeder, run the `make:seeder` [Artisan command](../digging-deeper/artisan-console.md). All seeders generated by the framework will be stored in the `database/seeders` directory: + +```shell +./artisan make:seeder UserSeeder +``` + +By default, a seeder struct has two methods: `Signature` and `Run`. The `Signature` method sets the name of the seeder, while the `Run` method is triggered when the `db:seed` Artisan command is executed. You can use the `Run` method to insert data into your database in any way you prefer. + +To illustrate, we can customize the `DatabaseSeeder` struct by adding a database insert statement to the `Run` method. + +```go +package seeders + +import ( + "github.com/goravel/framework/contracts/database/seeder" + + "goravel/app/facades" + "goravel/app/models" +) + +type DatabaseSeeder struct { +} + +// Signature The name and signature of the seeder. +func (s *DatabaseSeeder) Signature() string { + return "DatabaseSeeder" +} + +// Run executes the seeder logic. +func (s *DatabaseSeeder) Run() error { + user := models.User{ + Name: "goravel", + } + return facades.Orm().Query().Create(&user) +} +``` + +## Calling Additional Seeders + +Within the `DatabaseSeeder` struct, you may use the `Call` method to execute additional seed structs. Using the `Call` method allows you to break up your database seeding into multiple files so that no single seeder struct becomes too large. The `Call` method accepts an array of seeder structs that should be executed: + +```go +// Run executes the seeder logic. +func (s *DatabaseSeeder) Run() error { + return facades.Seeder().Call([]seeder.Seeder{ + &UserSeeder{}, + }) +} +``` + +Framework also provides a `CallOnce` method, a seeder will be executed only once in the `db:seed` command: + +```go +// Run executes the seeder logic. +func (s *DatabaseSeeder) Run() error { + return facades.Seeder().CallOnce([]seeder.Seeder{ + &UserSeeder{}, + }) +} +``` + +## Running Seeders + +You may run the `db:seed` Artisan command to seed your database. By default, the `db:seed` command runs the `database/seeders/database_seeder.go` file, which may in turn invoke other seed classes. However, you may use the `--seeder` option to specify a specific seeder class to run individually: + +```shell +./artisan db:seed +``` + +If you want to execute other seeders when running the `db:seed` command, you can register the seeder in the `bootstrp/app.go::WithSeeders` function, if the seeder is generated by the `make:seeder` command, the framework will automatically register it. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithSeeders(Seeders). + WithConfig(config.Boot). + Create() +} + +./artisan db:seed --seeder=UserSeeder PhotoSeeder // The signature of seeder +``` + +You may also seed your database using the `migrate:fresh` and `migrate:refresh` command in combination with the `--seed` option, which will drop all tables and re-run all of your migrations. This command is useful for completely re-building your database. The `--seeder` option may be used to specify a specific seeder to run: + +```shell +./artisan migrate:fresh --seed + +./artisan migrate:fresh --seed --seeder=UserSeeder + +./artisan migrate:refresh --seed + +./artisan migrate:refresh --seed --seeder=UserSeeder +``` + +### Forcing Seeders To Run In Production + +Some seeding operations may cause you to alter or lose data. In order to protect you from running seeding commands against your production database, you will be prompted for confirmation before the seeders are executed in the `production` environment. To force the seeders to run without a prompt, use the `--force` flag: + +```shell +./artisan db:seed --force +``` From 072c156fc189a5312181aefabdde1a74c4c9846b Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:08 +0800 Subject: [PATCH 010/163] New translations artisan-console.md (Uzbek) [skip ci] Update translations (Uzbek) artisan-console.md --- uz_UZ/digging-deeper/artisan-console.md | 538 ++++++++++++++++++++++++ 1 file changed, 538 insertions(+) create mode 100644 uz_UZ/digging-deeper/artisan-console.md diff --git a/uz_UZ/digging-deeper/artisan-console.md b/uz_UZ/digging-deeper/artisan-console.md new file mode 100644 index 000000000..98fdf24ee --- /dev/null +++ b/uz_UZ/digging-deeper/artisan-console.md @@ -0,0 +1,538 @@ +# Artisan Console + +[[toc]] + +## Introduction + +Artisan is the CLI tool that comes with Goravel for interacting with the command line. You can access it using `facades.Artisan()`. This tool has several useful commands that can assist you in the development of your application. Utilize the following command to view all available commands. + +```shell +./artisan list + +# or +go run . artisan list +``` + +Each command also has a "help" flag that shows and explains the arguments and options associated with the command: + +```shell +./artisan migrate --help +``` + +Instead of repeating `./artisan ...` command, you may want to add an alias to your shell configuration with the terminal command below: + +```shell +echo -e "\r\nalias artisan=\"go run . artisan\"" >>~/.zshrc +``` + +Then you can simply run your commands like this: + +```shell +artisan make:controller DemoController +``` + +You can also use `artisan` shell script like this: + +### Generating Commands + +You can use the `make:command` command to create a new command in the `app/console/commands` directory. Don't worry if this directory does not exist in your application, it will be created the first time you run the `make:command` command: + +```shell +./artisan make:command SendEmails +./artisan make:command user/SendEmails +``` + +### Register Commands + +All commands should be registered via the `WithCommands` function in the `bootstrap/app.go` file: + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithCommands(Commands). + WithConfig(config.Boot). + Create() +} +``` + +A new command created by `make:command` will be registered automatically in the `bootstrap/commands.go::Commands()` function and the function will be called by `WithCommands`. You need register the command manually if you create the command file by yourself. + +### Command Structure + +After generating your command, assign suitable values to the signature and description properties of the struct. The `Handle` method will be called when your command is executed. You need to implement your logic in this method. + +```go +package commands + +import ( + "github.com/goravel/framework/contracts/console" + "github.com/goravel/framework/contracts/console/command" +) + +type SendEmails struct { +} + +// Signature The name and signature of the console command. +func (receiver *SendEmails) Signature() string { + return "send:emails" +} + +// Description The console command description. +func (receiver *SendEmails) Description() string { + return "Send emails" +} + +// Extend The console command extend. +func (receiver *SendEmails) Extend() command.Extend { + return command.Extend{} +} + +// Handle Execute the console command. +func (receiver *SendEmails) Handle(ctx console.Context) error { + return nil +} +``` + +## Command I/O + +### Retrieving Input + +When you write console commands, it's typical to collect user input through `arguments` or `options`. With Goravel, it's extremely easy to retrieve the arguments and options that the user provides. + +#### Arguments + +Follow the arguments after the command: + +```shell +./artisan send:emails SUBJECT EMAIL_1 EMAIL_2 +``` + +Definition: + +```go +// send:emails +func (receiver *SendEmails) Extend() command.Extend { + return command.Extend{ + Arguments: []command.Argument{ + &command.ArgumentString{ + Name: "subject", + Usage: "subject of email", + Required: true, + }, + &command.ArgumentStringSlice{ + Name: "emails", + Usage: "target emails", + Min: 1, + Max: -1, + }, + }, + } +} +``` + +Supported agrument types : `ArgumentFloat32`, `ArgumentFloat64`, `ArgumentInt`, `ArgumentInt8`, `ArgumentInt16`, `ArgumentInt32`, `ArgumentInt64`, `ArgumentString`, `ArgumentUint`, `ArgumentUint8`, `ArgumentUint16`, `ArgumentUint32`, `ArgumentUint64`, `ArgumentTimestamp`, `ArgumentFloat32Slice`, `ArgumentFloat64Slice`, `ArgumentIntSlice`, `ArgumentInt8Slice`, `ArgumentInt16Slice`, `ArgumentInt32Slice`, `ArgumentInt64Slice`, `ArgumentStringSlice`, `ArgumentUintSlice`, `ArgumentUint8Slice`, `ArgumentUint16Slice`, `ArgumentUint32Slice`, `ArgumentUint64Slice`, `ArgumentTimestampSlice` + +Argument types with single value support next fields: + +```go + Name string // the name of this argument + Value T // the default value of this argument + Usage string // the usage text to show + Required bool // if this argument is required +``` + +Slice argument types fields: + +```go + Name string // the name of this argument + Value T // the default value of this argument + Usage string // the usage text to show + Min int // the min num of occurrences of this argument + Max int // the max num of occurrences of this argument, set to -1 for unlimited +``` + +Timestamp arguments additionally supports `Layouts []string` field, that should be filled with [supported layouts](https://pkg.go.dev/time#pkg-constants) + +Get arguments: + +```go +func (receiver *SendEmails) Handle(ctx console.Context) error { + subject := ctx.ArgumentString("subject") + emails := ctx.ArgumentStringSlice("emails") + + return nil +} +``` + +Alternatively, it is possible to access arguments directly: + +```go +func (receiver *SendEmails) Handle(ctx console.Context) error { + name := ctx.Argument(0) + email := ctx.Argument(1) + all := ctx.Arguments() + + return nil +} +``` + +#### Options + +Options, like arguments, are another form of user input. Options are prefixed by two hyphens (--) when they are provided via the command line. + +Definition: + +```go +func (receiver *ListCommand) Extend() command.Extend { + return command.Extend{ + Flags: []command.Flag{ + &command.StringFlag{ + Name: "lang", + Value: "default", + Aliases: []string{"l"}, + Usage: "language for the greeting", + }, + }, + } +} +``` + +Get: + +```go +func (receiver *ListCommand) Handle(ctx console.Context) error { + lang := ctx.Option("lang") + + return nil +} +``` + +Usage: + +```shell +./artisan emails --lang Chinese +./artisan emails -l Chinese +``` + +Except `command.StringFlag`, we can also use other type `Flag` and `Option*`: `StringSliceFlag`, `BoolFlag`, `Float64Flag`, `Float64SliceFlag`, `IntFlag`, `IntSliceFlag`, `Int64Flag`, `Int64SliceFlag`. + +### Prompting For Input + +#### Asking Questions + +In addition to arguments and options, you may also prompt the user for input during the execution of a command. The `Ask` method will prompt the user with the given question and return their response: + +```go +func (receiver *SendEmails) Handle(ctx console.Context) error { + email, err := ctx.Ask("What is your email address?") + + return err +} +``` + +Additionally, you can pass options to the `Ask` method as optional second argument: + +```go +func (receiver *SendEmails) Handle(ctx console.Context) error { + name, err := ctx.Ask("What is your name?", console.AskOption{ + Default: "Krishan", + }) + + return err +} + +// Available options +type AskOption struct { + // Default the default value for the input. + Default string + // Description the input description. + Description string + // Lines the number of lines for the input.(use for multiple lines text) + Lines int + // Limit the character limit for the input. + Limit int + // Multiple determines if input is single line or multiple lines text + Multiple bool + // Placeholder the input placeholder. + Placeholder string + // Prompt the prompt message.(use for single line input) + Prompt string + // Validate the input validation function. + Validate func(string) error +} +``` + +Sometimes you may need to hide the user input, such as when prompting for a password. You can use the `Secret` method to hide the user input: + +```go +func (receiver *SendEmails) Handle(ctx console.Context) error { + password, err := ctx.Secret("What is the password?", console.SecretOption{ + Validate: func (s string) error { + if len(s) < 8 { + return errors.New("password length should be at least 8") + } + return nil + }, + }) + + return err +} + +// Available options +type SecretOption struct { + // Default the default value for the input. + Default string + // Description the input description. + Description string + // Limit the character limit for the input. + Limit int + // Placeholder the input placeholder. + Placeholder string + // Validate the input validation function. + Validate func(string) error +} +``` + +#### Confirming Actions + +If you need to ask the user to confirm an action before proceeding, you may use the `Confirm` method. By default, this method will return `false` unless the user select affirmative option. + +```go +if ctx.Confirm("Do you wish to continue?") { + // ... +} +``` + +You can also pass a second argument to the `Confirm` method to customize the default value, label of the affirmative and negative buttons: + +```go +if ctx.Confirm("Do you wish to continue?", console.ConfirmOption{ + Default : true, + Affirmative : "Yes", + Negative : "No", +}) { + // ... +} + +// Available options +type ConfirmOption struct { + // Affirmative label for the affirmative button. + Affirmative string + // Default the default value for the input. + Default bool + // Description the input description. + Description string + // Negative label for the negative button. + Negative string +} +``` + +#### Single Select Questions + +If you need to ask the user to select an option from a list of options, you may use the `Choice` method. The `Choice` method will return the value of the selected option: + +```go +question := "What is your favorite programming language?" +options := []console.Choice{ + {Key: "go", Value: "Go"}, + {Key: "php", Value: "PHP"}, + {Key: "python", Value: "Python"}, + {Key: "cpp", Value: "C++", Selected: true}, +} +color, err := ctx.Choice(question, options) +``` + +Additionally, you can pass options to the `Choice` method as optional second argument: + +```go +question := "What is your favorite programming language?" +options := []console.Choice{ + {Key: "go", Value: "Go"}, + {Key: "php", Value: "PHP"}, + {Key: "python", Value: "Python"}, + {Key: "cpp", Value: "C++", Selected: true}, +} + +color, err := ctx.Choice(question, options, console.ChoiceOption{ + Default: "go", +}) + +// Available options +type ChoiceOption struct { + // Default the default value for the input. + Default string + // Description the input description. + Description string + // Validate the input validation function. + Validate func(string) error +} +``` + +#### Multiple Select Questions + +If you need to ask the user to select multiple options from a list of options, you may use the `MultiSelect` method. The `MultiSelect` method will return the values of the selected options: + +```go +question := "What are your favorite programming languages?" +options := []console.Choice{ + {Key: "go", Value: "Go"}, + {Key: "php", Value: "PHP"}, + {Key: "python", Value: "Python"}, + {Key: "cpp", Value: "C++", Selected: true}, +} +colors, err := ctx.MultiSelect(question, options) +``` + +Additionally, you can pass options to the `MultiSelect` method as optional second argument: + +```go +question := "What are your favorite programming languages?" +options := []console.Choice{ + {Key: "go", Value: "Go"}, + {Key: "php", Value: "PHP"}, + {Key: "python", Value: "Python"}, + {Key: "cpp", Value: "C++", Selected: true}, +} + +colors, err := ctx.MultiSelect(question, options, console.MultiSelectOption{ + Default: []string{"go", "php"}, +}) + +// Available options +type MultiSelectOption struct { + // Default the default value for the input. + Default []string + // Description the input description. + Description string + // Filterable determines if the choices can be filtered, type `/` to starting filter. + Filterable bool + // Limit the number of choices that can be selected. + Limit int + // Validate the input validation function. + Validate func([]string) error +} +``` + +### Writing Output + +Sometimes you may need to write output to the console. Goravel provides several methods to assist you in writing output to the console. Each of the method have their appropriate colorized output. For example, `Error` will display the text in red. + +```go +func (receiver *SendEmails) Handle(ctx console.Context) error { + ctx.Comment("This is a comment message") + ctx.Info("This is an info message") + ctx.Error("This is an error message") + ctx.Line("This is a line message") + ctx.Warning("This is a warning message") + return nil +} +``` + +There are few helpers to write to console with respective color: + +```go +ctx.Green("This is a green message") +ctx.Greenln("This is a green line message") +ctx.Red("This is a red message") +ctx.Redln("This is a red line message") +ctx.Yellow("This is a yellow message") +ctx.Yellowln("This is a yellow line message") +ctx.Black("This is a black message") +ctx.Blackln("This is a black line message") +``` + +You can use the `NewLine` method to write a new line to the console: + +```go +// write single blank line +ctx.NewLine() + +// write multiple blank lines +ctx.NewLine(2) +``` + +#### Progress Bars + +For long-running tasks, it is often helpful to provide the user with some indication of how much time the task will take. You may use the `WithProgressBar` method to display a progress bar. + +```go +items := []any{"item1", "item2", "item3"} +_, err := ctx.WithProgressBar(items, func(item any) error { + // performTask(item) + return nil +}) +``` + +Sometimes you may need to update the progress bar manually. You can use the `CreateProgressBar` method to update the progress bar: + +```go +users := []string{"user1", "user2", "user3"} +bar := ctx.CreateProgressBar(len(users)) + +err := bar.Start() + +for _, user := range users { + // process user + bar.Advance() + + // sleep for a while to simulate processing + time.Sleep(time.Millisecond * 50) +} + +err = bar.Finish() +``` + +#### Spinner + +If you need to display a spinner while a task is running, you may use the `Spinner` method. + +```go +err := ctx.Spinner("Loading...", console.SpinnerOption{ + Action: func() error { + // when to stop the spinner + time.Sleep(2 * time.Second) + return nil + }, +}) +``` + +### Divider + +To show terminal-width divider you may use `Divider` method. + +```go +ctx.Divider() // ---------- +ctx.Divider("=>") // =>=>=>=>=> +``` + +## Category + +You can set a set of commands to the same category, convenient in `./artisan list`: + +```go +// Extend The console command extend. +func (receiver *ConsoleMakeCommand) Extend() command.Extend { + return command.Extend{ + Category: "make", + } +} +``` + +## Programmatically Executing Commands + +Sometimes you may wish to execute an Artisan command outside of the CLI, you can use the `Call` method on the `facades.Artisan()` to operate this. + +```go +facades.Route().Get("/", func(c *gin.Context) { + facades.Artisan().Call("emails") + facades.Artisan().Call("emails --lang Chinese name") // With arguments and options +}) +``` + +## Disabling Print Colors + +Some commands print colors by default, such as the `list` command. However, in some terminals or logs, the color values may be garbled. You can use the `--no-ansi` option to disable the print colors: + +```shell +./artisan list --no-ansi +``` From f78aa7e8d1b219aad2919ec1f14d43eea360cf7f Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:09 +0800 Subject: [PATCH 011/163] New translations cache.md (Uzbek) [skip ci] Update translations (Uzbek) cache.md --- uz_UZ/digging-deeper/cache.md | 241 ++++++++++++++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 uz_UZ/digging-deeper/cache.md diff --git a/uz_UZ/digging-deeper/cache.md b/uz_UZ/digging-deeper/cache.md new file mode 100644 index 000000000..f34a8f919 --- /dev/null +++ b/uz_UZ/digging-deeper/cache.md @@ -0,0 +1,241 @@ +# Cache + +[[toc]] + +## Introduction + +Goravel provides an expandable cache module that can be operated using `facades.Cache()`. Goravel comes with a `memory` driver, for other drivers, please check the corresponding independent extension packages: + +| Driver | Link | +| ------ | ---------------------------------------------------------------------------------------------------- | +| Redis | [https://github.com/goravel/redis](https://github.com/goravel/redis) | + +## Configuration + +Make all custom configurations in `config/cache.go`. + +## Cache Usage + +### Inject Context + +```go +facades.Cache().WithContext(ctx) +``` + +### Accessing Multiple Cache Stores + +You may access various cache stores via the `Store` method. The key passed to the `Store` method should correspond to one of the stores listed in the "stores" configuration array in your cache configuration file: + +```go +value := facades.Cache().Store("redis").Get("foo") +``` + +### Retrieving Items From The Cache + +```go +value := facades.Cache().Get("goravel", "default") +value := facades.Cache().GetBool("goravel", true) +value := facades.Cache().GetInt("goravel", 1) +value := facades.Cache().GetString("goravel", "default") +``` + +You can pass a `func` as the default value. If the specified data does not exist in the cache, the result of `func` will be returned. The transitive closure method allows you to obtain default values from the database or other external services. Note the closure structure `func() any`. + +```go +value := facades.Cache().Get("goravel", func() any { + return "default" +}) +``` + +### Checking For Item Existence + +```go +bool := facades.Cache().Has("goravel") +``` + +### Incrementing / Decrementing Values + +The `Increment` and `Decrement` methods may be used to adjust the value of integer items in the cache. Both methods accept an optional second argument indicating the amount by which to increment or decrement the item's value: + +```go +facades.Cache().Increment("key") +facades.Cache().Increment("key", amount) +facades.Cache().Decrement("key") +facades.Cache().Decrement("key", amount) +``` + +### Retrieve & Store + +Sometimes you may want to get data from the cache, and when the requested cache item does not exist, the program can store a default value for you. + +```go +value, err := facades.Cache().Remember("goravel", 5*time.Second, func() (any, error) { + return "goravel", nil +}) +``` + +If the data you want does not exist in the cache, the closure passed to the `Remember` method will be executed, and then the result will be returned and placed in the cache. + +You can use the `RememberForever` method to retrieve data from the cache or store it permanently: + +```go +value, err := facades.Cache().RememberForever("goravel", func() (any, error) { + return "default", nil +}) +``` + +### Retrieve & Delete + +```go +value := facades.Cache().Pull("goravel", "default") +``` + +### Storing Items In The Cache + +```go +err := facades.Cache().Put("goravel", "value", 5*time.Second) +``` + +If the expiration time of the cache is set to `0`, the cache will be valid forever: + +```go +err := facades.Cache().Put("goravel", "value", 0) +``` + +### Store If Not Present + +The `Add` method stores data only if it's not in the cache. It returns `true` if storage is successful and `false` if it's not. + +```go +bool := facades.Cache().Add("goravel", "value", 5*time.Second) +``` + +### Storing Items Forever + +The `Forever` method can be used to store data persistently in the cache. Because these data will not expire, they must be manually deleted from the cache through the `Forget` method: + +```go +bool := facades.Cache().Forever("goravel", "value") +``` + +### Removing Items From The Cache + +```go +bool := facades.Cache().Forget("goravel") +``` + +You can use the `Flush` method to clear all caches: + +```go +bool := facades.Cache().Flush() +``` + +## Atomic Locks + +### Managing Locks + +Atomic locks allow for the manipulation of distributed locks without worrying about race conditions. You may create and manage locks using the `Lock` method: + +```go +lock := facades.Cache().Lock("foo", 10*time.Second) + +if (lock.Get()) { + // Lock acquired for 10 seconds... + + lock.Release() +} +``` + +The `Get` method also accepts a closure. After the closure is executed, Goravel will automatically release the lock: + +```go +facades.Cache().Lock("foo").Get(func () { + // Lock acquired for 10 seconds and automatically released... +}); +``` + +If the lock is not available at the moment you request it, you may instruct Goravel to wait for a specified number of seconds. If the lock can not be acquired within the specified time limit, will return `false`: + +```go +lock := facades.Cache().Lock("foo", 10*time.Second) +// Lock acquired after waiting a maximum of 5 seconds... +if (lock.Block(5*time.Second)) { + lock.Release() +} +``` + +The example above may be simplified by passing a closure to the `Block` method. When a closure is passed to this method, Goravel will attempt to acquire the lock for the specified number of seconds and will automatically release the lock once the closure has been executed: + +```go +facades.Cache().Lock("foo", 10*time.Second).Block(5*time.Second, func () { + // Lock acquired after waiting a maximum of 5 seconds... +}) +``` + +If you would like to release a lock without respecting its current owner, you may use the `ForceRelease` method: + +```go +facades.Cache().Lock("processing").ForceRelease(); +``` + +## Adding Custom Cache Drivers + +### Configuration + +If you want to define a completely custom driver, you can specify the `custom` driver type in the `config/cache.go` configuration file. +Then include a `via` option to implement a `framework/contracts/cache/Driver` interface: + +```go +//config/cache.go +"stores": map[string]interface{}{ + "memory": map[string]any{ + "driver": "memory", + }, + "custom": map[string]interface{}{ + "driver": "custom", + "via": &Logger{}, + }, +}, +``` + +### Implement Custom Driver + +Implement the `framework/contracts/cache/Driver` interface, files can be stored in the `app/extensions` folder (modifiable). + +```go +// framework/contracts/cache/Driver +package cache + +import "time" + +type Driver interface { + // Add Driver an item in the cache if the key does not exist. + Add(key string, value any, t time.Duration) bool + Decrement(key string, value ...int) (int, error) + // Forever Driver an item in the cache indefinitely. + Forever(key string, value any) bool + // Forget Remove an item from the cache. + Forget(key string) bool + // Flush Remove all items from the cache. + Flush() bool + // Get Retrieve an item from the cache by key. + Get(key string, def ...any) any + GetBool(key string, def ...bool) bool + GetInt(key string, def ...int) int + GetInt64(key string, def ...int64) int64 + GetString(key string, def ...string) string + // Has Check an item exists in the cache. + Has(key string) bool + Increment(key string, value ...int) (int, error) + Lock(key string, t ...time.Duration) Lock + // Put Driver an item in the cache for a given time. + Put(key string, value any, t time.Duration) error + // Pull Retrieve an item from the cache and delete it. + Pull(key string, def ...any) any + // Remember Get an item from the cache, or execute the given Closure and store the result. + Remember(key string, ttl time.Duration, callback func() (any, error)) (any, error) + // RememberForever Get an item from the cache, or execute the given Closure and store the result forever. + RememberForever(key string, callback func() (any, error)) (any, error) + WithContext(ctx context.Context) Driver +} +``` From 2c7b5f1f6581abd110bf1b5fc7f040b56a82aedd Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:10 +0800 Subject: [PATCH 012/163] New translations color.md (Uzbek) [skip ci] Update translations (Uzbek) color.md --- uz_UZ/digging-deeper/color.md | 52 +++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 uz_UZ/digging-deeper/color.md diff --git a/uz_UZ/digging-deeper/color.md b/uz_UZ/digging-deeper/color.md new file mode 100644 index 000000000..b048ea7c7 --- /dev/null +++ b/uz_UZ/digging-deeper/color.md @@ -0,0 +1,52 @@ +# Color + +[[toc]] + +## Introduction + +The `color` package provides a set of functions to colorize the output of the terminal using [PTerm](https://github.com/pterm/pterm) library. + +## Specific Color + +The package provides methods to create printers for specific colors. These methods allow you to easily colorize terminal output. + +- `color.Red()` +- `color.Green()` +- `color.Yellow()` +- `color.Blue()` +- `color.Magenta()` +- `color.Cyan()` +- `color.White()` +- `color.Black()` +- `color.Gray()` +- `color.Default()` + +### Printer Methods + +A `contracts/support.Printer` provides the following methods to print or format text with color: + +- `Print` - Print text +- `Println` - Print text with a new line +- `Printf` - Print formatted text +- `Sprint` - Return colored text +- `Sprintln` - Return colored text with a new line +- `Sprintf` - Return formatted colored text + +```go +import "github.com/goravel/framework/support/color" + +color.Blue().Println("Hello, Goravel!") +color.Green().Printf("Hello, %s!", "Goravel") +``` + +## Custom Color + +### `color.New` + +The `color.New` function creates a new color printer. You can use this object to colorize the output of the terminal. + +```go +import "github.com/goravel/framework/support/color" + +color.New(color.FgRed).Println("Hello, Goravel!") +``` From aed1d4d38e950bae655f9eaa605b571eb98d41a5 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:10 +0800 Subject: [PATCH 013/163] New translations event.md (Uzbek) [skip ci] Update translations (Uzbek) event.md --- uz_UZ/digging-deeper/event.md | 177 ++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 uz_UZ/digging-deeper/event.md diff --git a/uz_UZ/digging-deeper/event.md b/uz_UZ/digging-deeper/event.md new file mode 100644 index 000000000..35ba3f365 --- /dev/null +++ b/uz_UZ/digging-deeper/event.md @@ -0,0 +1,177 @@ +# Events + +[[toc]] + +## Introduction + +Goravel's events provide a simple observer pattern implementation, allowing you to subscribe and listen to various events that occur within your application. Event classes are typically stored in the `app/events` directory, while their listeners are stored in `app/listeners`. Don't worry if you don't see these directories in your application as they will be created for you as you generate events and listeners using Artisan console commands. + +Events serve as a great way to decouple various aspects of your application, as a single event can have multiple listeners that do not depend on each other. For example, you may wish to send a Slack notification to your user each time an order is shipped. Instead of coupling your order processing code to your Slack notification code, you can raise an `app/events/OrderShipped` event which a listener can receive and use to dispatch a Slack notification. + +## Register Events & Listeners + +All events and listeners should be registered via the `WithEvents` function in the `bootstrap/app.go` file: + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithEvents(func() map[event.Event][]event.Listener { + return map[event.Event][]event.Listener{ + events.NewOrderShipped(): { + listeners.NewSendShipmentNotification(), + }, + } + }). + WithConfig(config.Boot). + Create() +} +``` + +### Generating Events & Listeners + +You can use the `make:event` and `make:listener` Artisan commands to generate individual events and listeners: + +```go +./artisan make:event PodcastProcessed +./artisan make:event user/PodcastProcessed + +./artisan make:listener SendPodcastNotification +./artisan make:listener user/SendPodcastNotification +``` + +## Defining Events + +An event class is essentially a data container that holds the information related to the event, the `Handle` method of `event` passes in and returns the `[]event.Arg` structure, which can be used to process data. The processed data will then be passed on to all associated `listeners`. For example, let's assume an `app\events\OrderShipped` event: + +```go +package events + +import "github.com/goravel/framework/contracts/event" + +type OrderShipped struct {} + +func (receiver *OrderShipped) Handle(args []event.Arg) ([]event.Arg, error) { + return args, nil +} +``` + +## Defining Listeners + +Next, let's take a look at the listener for our example event. Event listeners receive `[]event.Arg` of the event `Handle` method returns. Within the `Handle` method, you may perform any actions necessary to respond to the event: + +```go +package listeners + +import ( + "github.com/goravel/framework/contracts/event" +) + +type SendShipmentNotification struct {} + +func (receiver *SendShipmentNotification) Signature() string { + return "send_shipment_notification" +} + +func (receiver *SendShipmentNotification) Queue(args ...any) event.Queue { + return event.Queue{ + Enable: false, + Connection: "", + Queue: "", + } +} + +func (receiver *SendShipmentNotification) Handle(args ...any) error { + return nil +} +``` + +### Stopping The Propagation Of An Event + +Sometimes, you may wish to stop the propagation of an event to other listeners. You may do so by returning an error from your listener's `Handle` method. + +## Queued Event Listeners + +Queueing listeners can be beneficial if your listener is going to perform a slow task such as sending an email or making an HTTP request. Before using queued listeners, make sure to [configure your queue](queues.md) and start a queue worker on your server or local development environment. + +```go +package listeners + +... + +func (receiver *SendShipmentNotification) Queue(args ...any) event.Queue { + return event.Queue{ + Enable: false, + Connection: "", + Queue: "", + } +} + +func (receiver *SendShipmentNotification) Handle(args ...any) error { + name := args[0] + + return nil +} +``` + +### Queued Event Listeners & Database Transactions + +When queued listeners are dispatched within database transactions, the queue may process them before the database transaction has been committed. When this happens, any updates you have made to models or database records during the database transaction may not yet be reflected in the database. In addition, any models or database records created within the transaction may not exist in the database. If your listener depends on these models, unexpected errors can occur when the job that dispatches the queued listener is processed. At this time, the event needs to be placed outside the database transactions. + +## Dispatching Events + +We can dispatch Events by `facades.Event().Job().Dispatch()` method. + +```go +package controllers + +import ( + "github.com/goravel/framework/contracts/event" + "github.com/goravel/framework/contracts/http" + + "goravel/app/events" + "goravel/app/facades" +) + +type UserController struct { +} + +func (r UserController) Show(ctx http.Context) { + err := facades.Event().Job(&events.OrderShipped{}, []event.Arg{ + {Type: "string", Value: "Goravel"}, + {Type: "int", Value: 1}, + }).Dispatch() +} +``` + +## `event.Arg.Type` Supported Types + +```go +bool +int +int8 +int16 +int32 +int64 +uint +uint8 +uint16 +uint32 +uint64 +float32 +float64 +string +[]bool +[]int +[]int8 +[]int16 +[]int32 +[]int64 +[]uint +[]uint8 +[]uint16 +[]uint32 +[]uint64 +[]float32 +[]float64 +[]string +``` From 46ca75b8bf882a3fa682ade2364e8907eeeed042 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:12 +0800 Subject: [PATCH 014/163] New translations filesystem.md (Uzbek) [skip ci] Update translations (Uzbek) filesystem.md --- uz_UZ/digging-deeper/filesystem.md | 340 +++++++++++++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 uz_UZ/digging-deeper/filesystem.md diff --git a/uz_UZ/digging-deeper/filesystem.md b/uz_UZ/digging-deeper/filesystem.md new file mode 100644 index 000000000..a8dce3f32 --- /dev/null +++ b/uz_UZ/digging-deeper/filesystem.md @@ -0,0 +1,340 @@ +# File Storage + +[[toc]] + +## Introduction + +The Goravel provides simple drivers for working with local filesystems, Amazon S3, Aliyun OSS, Tencent COS, Minio and Cloudinary. Even better, switching between these storage options between your local development machine and production server is amazingly simple as the API remains the same for each system. Goravel comes with a `local` driver, for other drivers, please check the corresponding independent extension package: + +| Driver | Link | +| ------ | ---------------------------------------------------------------------------------------------------- | +| S3 | [https://github.com/goravel/s3](https://github.com/goravel/s3) | +| OSS | [https://github.com/goravel/oss](https://github.com/goravel/oss) | +| COS | [https://github.com/goravel/cos](https://github.com/goravel/cos) | +| Minio | [https://github.com/goravel/minio](https://github.com/goravel/minio) | + +## Configuration + +Goravel's filesystem configuration file is located at `config/filesystems.go`. Within this file, you may configure all of your filesystem "disks", each disk represents a particular storage driver and storage location. + +> You may configure as many disks as you like and may even have multiple disks that use the same driver. + +### The Local Driver + +When using the `local` driver, all file operations are relative to the `root` directory defined in your `filesystems` configuration file. By default, this value is set to the `storage/app` directory. Therefore, the following method would write to `storage/app/example.txt`: + +```go +facades.Storage().Put("example.txt", "Contents") +``` + +### The Public Disk + +The `public`` disk included in your application's `filesystems`configuration file is intended for files that are going to be publicly accessible. By default, the`public`disk uses the`local`driver and stores its files in`storage/app/public\`. If you want to visit these file from web, you can create a file routing: + +```go +facades.Route().Static("storage", "./storage/app/public") +``` + +## Obtaining Disk Instances + +The `Storage` facade may be used to interact with any of your configured disks. For example, you may use the `Put` method on the facade to store an avatar on the default disk. If you call methods on the `Storage` facade without first calling the `Disk` method, the method will automatically be passed to the default disk: + +```go +facades.Storage().Put("avatars/1.png", "Contents") +``` + +If your application interacts with multiple disks, you may use the `Disk` method on the `Storage` facade to work with files on a particular disk: + +```go +facades.Storage().Disk("s3").Put("avatars/1.png", "Contents") +``` + +## Inject Context + +```go +facades.Storage().WithContext(ctx).Put("avatars/1.png", "Contents") +``` + +## Retrieving Files + +The `Get` method may be used to retrieve the contents of a file. The raw string contents of the file will be returned by the method. Remember, all file paths should be specified relative to the disk's `root` location: + +```go +content := facades.Storage().Get("file.jpg") +``` + +The `Exists` method may be used to determine if a file exists on the disk: + +```go +if (facades.Storage().Disk("s3").Exists("file.jpg")) { + // ... +} +``` + +The `Missing` method may be used to determine if a file is missing from the disk: + +```go +if (facades.Storage().Disk("s3").Missing("file.jpg")) { + // ... +} +``` + +### File URLs + +You may use the `Url` method to get the URL for a given file. If you are using the `local` driver, this will typically just prepend `/storage` to the given path and return a relative URL to the file. If you are using the `s3` driver, the fully qualified remote URL will be returned: + +```go +url := facades.Storage().Url("file.jpg") +``` + +> When using the `local` driver, the return value of `Url` is not URL encoded. For this reason, we recommend always storing your files using names that will create valid URLs. + +#### Temporary URLs + +Using the `TemporaryUrl` method, you may create temporary URLs to files stored using the Non-local driver. This method accepts a path and a `Time` instance specifying when the URL should expire: + +```go +url, err := facades.Storage().TemporaryUrl( + "file.jpg", time.Now().Add(5*time.Minute) +) +``` + +### File Metadata + +In addition to reading and writing files, Goravel can also provide information about the files themselves: + +```go +size := facades.Storage().Size("file.jpg") +``` + +The `LastModified` method returns the last modified time of the file: + +```go +time, err := facades.Storage().LastModified("file.jpg") +``` + +The MIME type of a given file may be obtained via the `MimeType` method: + +```go +mime, err := facades.Storage().MimeType("file.jpg") +``` + +Also can use the `NewFile` method: + +```go +import "github.com/goravel/framework/filesystem" + +file, err := filesystem.NewFile("./logo.png") +size, err := file.Size() +lastModified, err := file.LastModified() +mime, err := file.MimeType() +``` + +### File Paths + +To obtain the path for a specific file, you can utilize the `Path` method. When using the `local` driver, this will provide you with the relative path to the file. However, if you are using a driver like `s3`, the method will give you the file's relative path within the bucket: + +```go +path := facades.Storage().Path("file.jpg") +``` + +## Storing Files + +The `Put` method may be used to store file contents on a disk. Remember, all file paths should be specified relative to the "root" location configured for the disk: + +```go +err := facades.Storage().Put("file.jpg", contents) +``` + +You can also use `PutFile` and `PutFileAs` to save files directly on disk: + +```go +import "github.com/goravel/framework/filesystem" + +// Automatically generate a unique ID for filename... +file, err := filesystem.NewFile("./logo.png") +path := facades.Storage().PutFile("photos", file) + +// Manually specify a filename... +file, err := filesystem.NewFile("./logo.png") +path := facades.Storage().PutFileAs("photos", file, "photo.jpg") +``` + +There are a few important things to note about the `PutFile` method. Note that we only specified a directory name and not a filename. By default, the `PutFile` method will generate a unique ID to serve as the filename. The file's extension will be determined by examining the file's MIME type. The path to the file will be returned by the `PutFile` method so you can store the path, including the generated filename, in your database. + +### Copying & Moving Files + +The `Copy` method may be used to copy an existing file to a new location on the disk, while the `Move` method may be used to rename or move an existing file to a new location: + +```go +err := facades.Storage().Copy("old/file.jpg", "new/file.jpg") + +err := facades.Storage().Move("old/file.jpg", "new/file.jpg") +``` + +### File Uploads + +In web applications, one of the most common use cases for storing files is storing user-uploaded files such as photos and documents. Goravel makes it very easy to store uploaded files using the `Store` method on an uploaded file instance. Call the `Store` method with the path at which you wish to store the uploaded file: + +```go +func (r *UserController) Show(ctx http.Context) { + file, err := ctx.Request().File("avatar") + path, err := file.Store("avatars") +} +``` + +There are a few important things to note about this example. Note that we only specified a directory name, not a filename. By default, the `Store` method will generate a unique ID to serve as the filename. The file's extension will be determined by examining the file's MIME type. The path to the file will be returned by the `Store` method so you can store the path, including the generated filename, in your database. + +You may also call the `PutFile` method on the `Storage` facade to perform the same file storage operation as the example above: + +```go +import "github.com/goravel/framework/filesystem" + +file, err := filesystem.NewFile("./logo.png") +path := facades.Storage().PutFile("photos", file) +``` + +### Specifying A File Name + +If you do not want a filename to be automatically assigned to your stored file, you may use the `StoreAs` method, which receives the path, the filename, and the (optional) disk as its arguments: + +```go +file, err := ctx.Request().File("avatar") +path, err := file.StoreAs("avatars", "name") +``` + +You may also use the `PutFileAs` method on the Storage facade, which will perform the same file storage operation as the example above: + +```go +import "github.com/goravel/framework/filesystem" + +file, err := filesystem.NewFile("./logo.png") +path := facades.Storage().PutFileAs("photos", file, "name") +``` + +> If the file name specified by `StoreAs` and `PutFileAs` doesn't have a suffix, the suffix is automatically added based on the MIME of the file; otherwise, the specified file name is used directly. + +### Specifying A Disk + +By default, this uploaded file's `Store` method will use your default disk. If you would like to specify another disk, please use the `Disk` method: + +```go +func (r *UserController) Show(ctx http.Context) { + file, err := ctx.Request().File("avatar") + path, err := file.Disk("s3").Store("avatars") +} +``` + +### Other Uploaded File Information + +If you would like to get the original name and extension of the uploaded file, you may do so using the `GetClientOriginalName` and `GetClientOriginalExtension` methods: + +```go +file, err := ctx.Request().File("avatar") + +name := file.GetClientOriginalName() +extension := file.GetClientOriginalExtension() +``` + +However, keep in mind that the `GetClientOriginalName` and `GetClientOriginalExtension` methods are considered unsafe, as the file name and extension may be tampered with by a malicious user. For this reason, you should typically prefer the `HashName` and `Extension` methods to get a name and an extension for the given file upload: + +```go +file, err := ctx.Request().File("avatar") + +name := file.HashName() // Generate a unique, random name... +extension, err := file.Extension() // Determine the file's extension based on the file's MIME type... +``` + +## Deleting Files + +The `Delete` method accepts a single filename or an array of files to delete: + +```go +err := facades.Storage().Delete("file.jpg") +err := facades.Storage().Delete("file.jpg", "file2.jpg") +``` + +If necessary, you may specify the disk that the file should be deleted from: + +```go +err := facades.Storage().Disk("s3").Delete("file.jpg") +``` + +## Directories + +### Get All Files Within A Directory + +The `Files` method returns a slice of all of the files in a given directory. If you would like to retrieve a list of all files within a given directory including all subdirectories, you may use the `AllFiles` method: + +```go +files, err := facades.Storage().Disk("s3").Files("directory") +files, err := facades.Storage().Disk("s3").AllFiles("directory") +``` + +### Get All Directories Within A Directory + +The `Directories` method returns a slice of all the directories within a given directory. Additionally, you may use the `AllDirectories` method to get a list of all directories within a given directory and all of its subdirectories: + +```go +directories, err := facades.Storage().Disk("s3").Directories("directory") +directories, err := facades.Storage().Disk("s3").AllDirectories("directory") +``` + +### Create A Directory + +The `MakeDirectory` method will create the given directory, including any needed subdirectories: + +```go +err := facades.Storage().MakeDirectory(directory) +``` + +### Delete A Directory + +Finally, the `DeleteDirectory` method may be used to remove a directory and all of its files: + +```go +err := facades.Storage().DeleteDirectory(directory) +``` + +## Custom Filesystems + +You can set the `custom` driver in the `config/filesystems.go` file. + +```go +"custom": map[string]any{ + "driver": "custom", + "via": filesystems.NewLocal(), +}, +``` + +You need to implement the `github.com/goravel/framework/contracts/filesystem/Driver` interface in the `via` configuration item. + +```go +type Driver interface { + AllDirectories(path string) ([]string, error) + AllFiles(path string) ([]string, error) + Copy(oldFile, newFile string) error + Delete(file ...string) error + DeleteDirectory(directory string) error + Directories(path string) ([]string, error) + Exists(file string) bool + Files(path string) ([]string, error) + Get(file string) (string, error) + GetBytes(file string) ([]byte, error) + LastModified(file string) (time.Time, error) + MakeDirectory(directory string) error + MimeType(file string) (string, error) + Missing(file string) bool + Move(oldFile, newFile string) error + Path(file string) string + Put(file, content string) error + PutFile(path string, source File) (string, error) + PutFileAs(path string, source File, name string) (string, error) + Size(file string) (int64, error) + TemporaryUrl(file string, time time.Time) (string, error) + WithContext(ctx context.Context) Driver + Url(file string) string +} +``` + +> Note: Since the configuration has not been loaded when the custom driver is registered, so please use `facades.Config().Env()` to obtain the configuration in the custom driver. From 7123d4c6528060cce99ca85ce3139fc432d91f9e Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:13 +0800 Subject: [PATCH 015/163] New translations helpers.md (Uzbek) [skip ci] Update translations (Uzbek) helpers.md --- uz_UZ/digging-deeper/helpers.md | 762 ++++++++++++++++++++++++++++++++ 1 file changed, 762 insertions(+) create mode 100644 uz_UZ/digging-deeper/helpers.md diff --git a/uz_UZ/digging-deeper/helpers.md b/uz_UZ/digging-deeper/helpers.md new file mode 100644 index 000000000..3dbe6c8fd --- /dev/null +++ b/uz_UZ/digging-deeper/helpers.md @@ -0,0 +1,762 @@ +# Helpers + +[[toc]] + +## Available Methods + +### Paths + +| | | | +| -------------------------------------------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------- | +| [path.App()](#path-app) | [path.Base()](#path-base) | [path.Config()](#path-config) | +| [path.Database()](#path-database) | [path.Storage()](#path-storage) | [path.Public()](#path-public) | +| [path.Resource()](#path-resource) | | | + +### Carbon + +| | | | +| ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | +| [carbon.Now()](#carbon-now) | [carbon.SetTimezone()](#carbon-settimezone) | [carbon.SetLocale()](#carbon-setlocale) | +| [carbon.SetTestNow()](#carbon-settestnow) | [carbon.ClearTestNow()](#carbon-cleartestnow) | [carbon.IsTestNow()](#carbon-istestnow) | +| [carbon.Parse()](#carbon-parse) | [carbon.ParseByLayout()](#carbon-parsebylayout) | [carbon.ParseByFormat()](#carbon-parsebyformat) | +| [carbon.FromTimestamp()](#carbon-fromtimestamp) | [carbon.FromTimestampMilli()](#carbon-fromtimestampmilli) | [carbon.FromTimestampMicro()](#carbon-fromtimestampmicro) | +| [carbon.FromTimestampNano()](#carbon-fromtimestampnano) | [carbon.FromDateTime()](#carbon-fromdatetime) | [carbon.FromDateTimeMilli()](#carbon-fromdatetimemilli) | +| [carbon.FromDateTimeMicro()](#carbon-fromdatetimemicro) | [carbon.FromDateTimeNano()](#carbon-fromdatetimenano) | [carbon.FromDate()](#carbon-fromdate) | +| [carbon.FromDateMilli()](#carbon-fromdatemilli) | [carbon.FromDateMicro()](#carbon-fromdatemicro) | [carbon.FromDateNano()](#carbon-fromdatenano) | +| [carbon.FromTime()](#carbon-fromtime) | [carbon.FromTimeMilli()](#carbon-fromtimemilli) | [carbon.FromTimeMicro()](#carbon-fromtimemicro) | +| [carbon.FromTimeNano()](#carbon-fromtimenano) | [carbon.FromStdTime()](#carbon-fromstdtime) | | + +### Debug + +| | | | +| -------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- | +| [debug.Dump()](#debug-dump) | [debug.SDump()](#debug-sdump) | [debug.FDump()](#debug-fdump) | + +### Maps + +| | | | +| -------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- | +| [maps.Add()](#maps-add) | [maps.Exists()](#maps-exists) | [maps.Forget()](#maps-forget) | +| [maps.Get()](#maps-get) | [maps.Has()](#maps-has) | [maps.HasAny()](#maps-hasany) | +| [maps.Only()](#maps-only) | [maps.Pull()](#maps-pull) | [maps.Set()](#maps-set) | +| [maps.Where()](#maps-where) | | | + +### Convert + +| | | | +| ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------- | +| [convert.Tap()](#convert-tap) | [convert.With()](#convert-with) | [convert.Transform()](#convert-transform) | +| [convert.Default()](#convert-default) | [convert.Pointer()](#convert-pointer) | | + +### Collect + +| | | | +| ---------------------------------------------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | +| [collect.Count()](#collect-count) | [collect.CountBy()](#collect-countby) | [collect.Each()](#collect-each) | +| [collect.Filter()](#collect-filter) | [collect.GroupBy()](#collect-groupby) | [collect.Keys()](#collect-keys) | +| [collect.Map()](#collect-map) | [collect.Max()](#collect-max) | [collect.Merge()](#collect-merge) | +| [collect.Min()](#collect-min) | [collect.Reverse()](#collect-reverse) | [collect.Shuffle()](#collect-shuffle) | +| [collect.Split()](#collect-split) | [collect.Sum()](#collect-sum) | [collect.Unique()](#collect-unique) | +| [collect.Values()](#collect-values) | | | + +## Paths + +```go +import "github.com/goravel/framework/support/path" +``` + +### `path.App()` + +The `path.App()` function returns the absolute path to your application's app directory. You may also use the `path.App()` function to generate a path to a file relative to the application directory: + +```go +path := path.App() +path := path.App("http/controllers/controller.go") +``` + +### `path.Base()` + +The `path.Base()` function returns the absolute path to your application's root directory. You may also use the `path.Base()` function to generate a path to a given file relative to the project root directory: + +```go +path := path.Base() +path := path.Base("vendor/bin") +``` + +### `path.Config()` + +The `path.Config()` function returns the absolute path to your application's config directory. You may also use the `path.Config()` function to generate a path to a given file within the application's configuration directory: + +```go +path := path.Config() +path := path.Config("app.go") +``` + +### `path.Database()` + +The `path.Database()` function returns the absolute path to your application's database directory. You may also use the `path.Database()` function to generate a path to a given file within the `database` directory: + +```go +path := path.Database() +path := path.Database("factories/user_factory.go") +``` + +### `path.Storage()` + +The `path.Storage()` function returns the absolute path to your application's storage directory. You may also use the `path.Storage()` function to generate a path to a given file within the `storage` directory: + +```go +path := path.Storage() +path := path.Storage("app/file.txt") +``` + +### `path.Public()` + +The `path.Public()` function returns the absolute path to your application's public directory. You may also use the `path.Public()` function to generate a path to a given file within the `public` directory: + +```go +path := path.Public() +path := path.Public("css/app.css") +``` + +### `path.Lang()` + +The `path.Lang()` function returns the absolute path to the `lang` directory. You may also use the `path.Lang()` function to generate a path to a given file within the `lang` directory: + +```go +path := path.Lang() +path := path.Lang("en.json") +``` + +### `path.Resource()` + +The `path.Resource()` function returns the absolute path to the `resource` directory. You may also use the `path.Resource()` function to generate a path to a given file within the `resource` directory: + +```go +path := path.Resource() +path := path.Resource("css/app.css") +``` + +## Carbon + +The `carbon` module of Goravel is an expansion by [dromara/carbon](https://github.com/dromara/carbon), please refer to the official documentation for details. + +```go +import "github.com/goravel/framework/support/carbon" +``` + +### `carbon.Now()` + +The `carbon.Now()` function gets current time: + +```go +carbon.Now() +``` + +### `carbon.SetTimezone()` + +The `carbon.SetTimezone()` function sets timezone: + +```go +carbon.SetTimezone(carbon.UTC) +``` + +### `carbon.SetLocale()` + +The `carbon.SetLocale()` function sets language locale, refer to [locales list](https://github.com/dromara/carbon/tree/master/lang) for all supported locales: + +```go +carbon.SetLocale("en") +``` + +### `carbon.SetTestNow()` + +The `carbon.SetTestNow()` function sets the time to a test value: + +```go +carbon.SetTestNow(carbon.Now()) +``` + +### `carbon.CleanTestNow()` + +The `carbon.CleanTestNow()` function clears the test now Carbon object: + +```go +carbon.CleanTestNow() +``` + +### `carbon.IsTestNow()` + +The `carbon.IsTestNow()` function determines whether the time is a test value: + +```go +carbon.IsTestNow() +``` + +### `carbon.Parse()` + +The `carbon.Parse()` function gets `Carbon` object by String: + +```go +carbon.Parse("2020-08-05 13:14:15") +``` + +### `carbon.ParseByLayout()` + +The `carbon.ParseByLayout()` function gets `Carbon` object by given value and layout: + +```go +carbon.ParseByLayout("2020-08-05 13:14:15", carbon.DateTimeLayout) +carbon.ParseByLayout("2020|08|05 13|14|15", []string{"2006|01|02 15|04|05", "2006|1|2 3|4|5"}) +``` + +### `carbon.ParseByFormat()` + +The `carbon.ParseByFormat()` function gets `Carbon` object by given value and format: + +```go +carbon.ParseByFormat("2020-08-05 13:14:15", carbon.DateTimeFormat) +carbon.ParseByFormat("2020|08|05 13|14|15", []string{"Y|m|d H|i|s", "y|m|d h|i|s"}) +``` + +### `carbon.FromTimestamp()` + +The `carbon.FromTimestamp()` function gets `Carbon` object by timestamp with second precision: + +```go +carbon.FromTimestamp(1577836800) +``` + +### `carbon.FromTimestampMilli()` + +The `carbon.FromTimestampMilli()` function gets `Carbon` object by timestamp with millisecond precision: + +```go +carbon.FromTimestampMilli(1649735755999) +``` + +### `carbon.FromTimestampMicro()` + +The `carbon.FromTimestampMicro()` function gets `Carbon` object by timestamp with microsecond precision: + +```go +carbon.FromTimestampMicro(1649735755999999) +``` + +### `carbon.FromTimestampNano()` + +The `carbon.FromTimestampNano()` function gets `Carbon` object by timestamp with nanosecond precision: + +```go +carbon.FromTimestampNano(1649735755999999999) +``` + +### `carbon.FromDateTime()` + +The `carbon.FromDateTime()` function gets `Carbon` object by year, month, day, hour, minute, second: + +```go +carbon.FromDateTime(2020, 1, 1, 0, 0, 0) +``` + +### `carbon.FromDateTimeMilli()` + +The `carbon.FromDateTimeMilli()` function gets `Carbon` object by year, month, day, hour, minute, second, millisecond: + +```go +carbon.FromDateTimeMilli(2020, 1, 1, 0, 0, 0, 999) +``` + +### `carbon.FromDateTimeMicro()` + +The `carbon.FromDateTimeMicro()` function gets `Carbon` object by year, month, day, hour, minute, second, microsecond: + +```go +carbon.FromDateTimeMicro(2020, 1, 1, 0, 0, 0, 999999) +``` + +### `carbon.FromDateTimeNano()` + +The `carbon.FromDateTimeNano()` function gets `Carbon` object by year, month, day, hour, minute, second, nanosecond: + +```go +carbon.FromDateTimeNano(2020, 1, 1, 0, 0, 0, 999999999) +``` + +### `carbon.FromDate()` + +The `carbon.FromDate()` function gets `Carbon` object by year, month, day: + +```go +carbon.FromDate(2020, 1, 1) +``` + +### `carbon.FromDateMilli()` + +The `carbon.FromDateMilli()` function gets `Carbon` object by year, month, day, millisecond: + +```go +carbon.FromDateMilli(2020, 1, 1, 999) +``` + +### `carbon.FromDateMicro()` + +The `carbon.FromDateMicro()` function gets `Carbon` object by year, month, day, microsecond: + +```go +carbon.FromDateMicro(2020, 1, 1, 999999) +``` + +### `carbon.FromDateNano()` + +The `carbon.FromDateNano()` function gets `Carbon` object by year, month, day, nanosecond: + +```go +carbon.FromDateNano(2020, 1, 1, 999999999) +``` + +### `carbon.FromTime()` + +The `carbon.FromTime()` function gets `Carbon` object by hour, minute, second: + +```go +carbon.FromTime(13, 14, 15) +``` + +### `carbon.FromTimeMilli()` + +The `carbon.FromTimeMilli()` function gets `Carbon` object by hour, minute, second, millisecond: + +```go +carbon.FromTimeMilli(13, 14, 15, 999) +``` + +### `carbon.FromTimeMicro()` + +The `carbon.FromTimeMicro()` function gets `Carbon` object by hour, minute, second, microsecond: + +```go +carbon.FromTimeMicro(13, 14, 15, 999999) +``` + +### `carbon.FromTimeNano()` + +The `carbon.FromTimeNano()` function gets `Carbon` object by hour, minute, second, nanosecond: + +```go +carbon.FromTimeNano(13, 14, 15, 999999999) +``` + +### `carbon.FromStdTime()` + +The `carbon.FromStdTime()` function gets `Carbon` object by `time.Time`: + +```go +carbon.FromStdTime(time.Now()) +``` + +## Debug + +```go +import "github.com/goravel/framework/support/debug" +``` + +### `debug.Dump()` + +The `debug.Dump()` function prints any variable: + +```go +debug.Dump(myVar1, myVar2, ...) +``` + +### `debug.FDump()` + +The `debug.FDump()` function prints any variable to `io.Writer`: + +```go +debug.FDump(someWriter, myVar1, myVar2, ...) +``` + +### `debug.SDump()` + +The `debug.SDump()` function prints any variable to `string`: + +```go +debug.SDump(myVar1, myVar2, ...) +``` + +## Maps + +```go +import "github.com/goravel/framework/support/maps" +``` + +### `maps.Add()` + +The `maps.Add()` function adds a new key-value pair to the given map if the key does not already exist in the map: + +```go +mp := map[string]any{"name": "Krishan"} +maps.Add(mp, "age", 22) +// map[string]any{"name": "Krishan", "age": 22} + +mp2 := map[string]string{} +maps.Add(mp2, "name", "Bowen") +maps.Add(mp2, "name", "Krishan") +// map[string]string{"name": "Bowen"} +``` + +### `maps.Exists()` + +The `maps.Exists()` function determines if the given key exists in the provided map: + +```go +mp := map[string]any{"name": "Krishan", "age": 22} + +maps.Exists(mp, "name") // true + +maps.Exists(mp, "email") // false +``` + +### `maps.Forget()` + +The `maps.Forget()` function removes the given key(s) from the provided map: + +```go +mp := map[string]string{"name": "Krishan", "age": "22"} + +maps.Forget(mp, "name", "age") +// map[string]string{} +``` + +### `maps.Get()` + +The `maps.Get()` function retrieves the value of the given key from the provided map. If the key does not exist, the default value will be returned: + +```go +mp := map[string]any{"name": "Bowen"} + +maps.Get(mp, "name", "Krishan") // Bowen + +maps.Get(mp, "age", 22) // 22 +``` + +### `maps.Has()` + +The `maps.Has()` function determines if the given key(s) exists in the provided map: + +```go +mp := map[string]any{"name": "Goravel", "language": "Go"} + +maps.Has(mp, "name", "language") // true + +maps.Has(mp, "name", "age") // false +``` + +### `maps.HasAny()` + +The `maps.HasAny()` function determines if any of the given key(s) exists in the provided map: + +```go +mp := map[string]any{"name": "Goravel", "language": "Go"} + +maps.HasAny(mp, "name", "age") // true + +maps.HasAny(mp, "age", "email") // false +``` + +### `maps.Only()` + +The `maps.Only()` function retrieves only the given key(s) from the provided map: + +```go +mp := map[string]any{"name": "Goravel", "language": "Go"} + +maps.Only(mp, "name") +// map[string]any{"name": "Goravel"} + +maps.Only(mp, "name", "age") +// map[string]any{"name": "Goravel"} +``` + +### `maps.Pull()` + +The `maps.Pull()` function retrieves and removes the given key from the provided map: + +```go +mp := map[string]any{"name": "Goravel", "language": "Go"} + +maps.Pull(mp, "name") +// map[string]any{"language": "Go"} +``` + +A default value can be provided as the third argument to the `maps.Pull()` function. This value will be returned if the key does not exist in the map: + +```go +mp := map[string]any{"name": "Goravel", "language": "Go"} + +maps.Pull(mp, "age", "default") +// map[string]any{"name": "Goravel", "language": "Go"} +``` + +### `maps.Set()` + +The `maps.Set()` function sets the given key and value in the provided map: + +```go +mp := map[string]any{"name": "Goravel"} + +maps.Set(mp, "language", "Go") +// map[string]any{"name": "Goravel", "language": "Go"} +``` + +### `maps.Where()` + +The `maps.Where()` function filters the provided map using the given callback: + +```go +mp := map[string]string{"name": "Goravel", "language": "Go"} + +maps.Where(mp, func(key string, value string) bool { + return key == "name" +}) +// map[string]string{"name": "Goravel"} +``` + +## Convert + +```go +import "github.com/goravel/framework/support/convert" +``` + +### `convert.Tap()` + +The `convert.Tap()` function passes the given value to the provided callback and returns the value: + +```go +convert.Tap("Goravel", func(value string) { + fmt.Println(value + " Framework") +}) +// Goravel + +mp := map[string]string{"name": "Goravel"} +convert.Tap(mp, func(value map[string]string) { + mp["language"] = "Go" +}) +// map[string]string{"name": "Goravel", "language": "Go"} +``` + +### `convert.Transform()` + +The `convert.Transform()` transforms the given value using the provided callback and returns the result: + +```go +convert.Transform(1, strconv.Itoa) +// "1" + +convert.Transform("foo", func(s string) *foo { + return &foo{Name: s} +}) +// &foo{Name: "foo"} +``` + +### `convert.With()` + +The `convert.With()` executes the given callback with the provided value and returns the result of the callback: + +```go +convert.With("Goravel", func(value string) string { + return value + " Framework" +}) +// Goravel Framework +``` + +### `convert.Default()` + +The `convert.Default()` method returns first non-zero value. If all values are zero, it returns zero value. + +```go +convert.Default("", "foo") // foo + +convert.Default("bar", "foo") // bar + +convert.Default(0, 1) // 1 +``` + +### `convert.Pointer()` + +The `convert.Pointer()` method returns the pointer of the given value. + +```go +convert.Pointer("foo") // *string("foo") + +convert.Pointer(1) // *int(1) +``` + +## Collect + +```go +import "github.com/goravel/framework/support/collect" +``` + +### `collect.Count()` + +The `collect.Count()` function returns the number of items in the given collection: + +```go +collect.Count([]string{"Goravel", "Framework"}) // 2 +``` + +### `collect.CountBy()` + +The `collect.CountBy()` function counts the occurrences for which the predicate is true: + +```go +collect.CountBy([]string{"Goravel", "Framework"}, func(value string) bool { + return strings.Contains(value, "Goravel") +}) +// 1 +``` + +### `collect.Each()` + +The `collect.Each()` function iterates over the items in the given collection and passes each item to the given callback: + +```go +collect.Each([]string{"Goravel", "Framework"}, func(value string, index int) { + fmt.Println(index + 1, value) +}) +// 1 Goravel +// 2 Framework +``` + +### `collect.Filter()` + +The `collect.Filter()` function filters the items in the collection using the given callback: + +```go +collect.Filter([]string{"Goravel", "Framework"}, func(value string) bool { + return strings.Contains(value, "Goravel") +}) +// []string{"Goravel"} +``` + +### `collect.GroupBy()` + +The `collect.GroupBy()` function groups the items in the collection by the result of the given callback: + +```go +// use example of complex map slice (use different example) +collect.GroupBy([]map[string]string{ + {"class": "1", "Name": "Rohan"}, + {"class": "2", "Name": "Bowen"}, + {"class": "2", "Name": "Krishan"}, +}, func(value map[string]string) string { + return value["class"] +}) +// map[string][]map[string]string{ +// "1": []map[string]string{{"class": "1", "Name": "Rohan"}}, +// "2": []map[string]string{{"class": "2", "Name": "Bowen"}, {"class": "2", "Name": "Krishan"}}, +// } +``` + +### `collect.Keys()` + +The `collect.Keys()` function returns all the keys for the items in the collection: + +```go +collect.Keys(map[string]string{"name": "Goravel", "language": "Go"}) +// []string{"name", "language"} +``` + +### `collect.Map()` + +The `collect.Map()` function converts one type of collection into another using the given iteratee: + +```go +collect.Map([]string{"Goravel", "Framework"}, func(value string, _ int) string { + return strings.ToUpper(value) +}) +// []string{"GORAVEL", "FRAMEWORK"} +``` + +### `collect.Max()` + +The `collect.Max()` function returns the maximum value of the given collection: + +```go +collect.Max([]int{1, 2, 3, 4, 5}) // 5 +``` + +### `collect.Merge()` + +The `collect.Merge()` function merges the given maps into a single map: + +```go +collect.Merge(map[string]string{"name": "Goravel"}, map[string]string{"language": "Go"}) +// map[string]string{"name": "Goravel", "language": "Go"} + +collect.Merge(map[string]string{"name": "Goravel"}, map[string]string{"name": "Framework"}) +// map[string]string{"name": "Framework"} +``` + +### `collect.Min()` + +The `collect.Min()` function returns the minimum value of the given collection: + +```go +collect.Min([]int{1, 2, 3, 4, 5}) // 1 +``` + +### `collect.Reverse()` + +The `collect.Reverse()` function reverses the items in the collection: + +```go +collect.Reverse([]string{"Goravel", "Framework"}) +// []string{"Framework", "Goravel"} +``` + +### `collect.Shuffle()` + +The `collect.Shuffle()` function shuffles the items in the collection: + +```go +collect.Shuffle([]int{1, 2, 3, 4, 5}) +// []int{3, 1, 5, 2, 4}(example) +``` + +### `collect.Split()` + +The `collect.Split()` function splits a collection into the groups of the given length. If the collection can't be split evenly, the final chunk will contain the remaining items: + +```go +collect.Split([]int{1, 2, 3, 4, 5}, 2) +// [][]int{{1, 2}, {3, 4}, {5}} +``` + +### `collect.Sum()` + +The `collect.Sum()` function returns the sum of all items in the collection: + +```go +collect.Sum([]int{1, 2, 3, 4, 5}) // 15 +``` + +### `collect.Unique()` + +The `collect.Unique()` method returns the duplicate-free collection where in case of duplicate values, only the first occurrence will be kept: + +```go +collect.Unique([]string{"Goravel", "Framework", "Goravel"}) +// []string{"Goravel", "Framework"} +``` + +### `collect.Values()` + +The `collect.Values()` function returns all the values of the given collection: + +```go +collect.Values(map[string]string{"name": "Goravel", "language": "Go"}) +// []string{"Goravel", "Go"} +``` From 2671b57b80bc11a13e58f667507b8733a1d5af34 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:14 +0800 Subject: [PATCH 016/163] New translations http-client.md (Uzbek) [skip ci] Update translations (Uzbek) http-client.md --- uz_UZ/digging-deeper/http-client.md | 485 ++++++++++++++++++++++++++++ 1 file changed, 485 insertions(+) create mode 100644 uz_UZ/digging-deeper/http-client.md diff --git a/uz_UZ/digging-deeper/http-client.md b/uz_UZ/digging-deeper/http-client.md new file mode 100644 index 000000000..f36be17e9 --- /dev/null +++ b/uz_UZ/digging-deeper/http-client.md @@ -0,0 +1,485 @@ +# HTTP Client + +[[toc]] + +## Introduction + +In software development, there are many instances when you need to call an API to fetch data— +whether it's connecting to a microservice or accessing a third-party API. In such cases, +Goravel offers an easy-to-use, expressive, and minimalist API built on the standard `net/http` library, +all designed to enhance the developer experience. + +## Configuration + +Goravel's HTTP client is built on top of the `net/http.Client` for making HTTP requests. If you need to tweak its internal settings, just update the `clients` property in the `config/http.go` file. + +## Making Requests + +The Http facade provides a convenient way to make HTTP requests using familiar verbs: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, and `OPTIONS`. + +**Example: GET Request** + +```go +response, err := facades.Http().Get("https://example.com") +``` + +Each HTTP verb method returns a `response` of type `framework/contracts/http/client.Response` and an `err` if the request fails. + +You can use the `Client` function to specify which HTTP client configuration to use: + +```go +response, err := facades.Http().Client("github").Get("https://example.com") +``` + +### Response Interface + +The `framework/contracts/http/client.Response` interface provides the following methods to interact with the HTTP response: + +```go +type Response interface { + Bind(value any) error // Bind the response body to a struct + Body() (string, error) // Get the response body as a string + ClientError() bool // Check if the status code is in the 4xx range + Cookie(name string) *http.Cookie // Get a specific cookie + Cookies() []*http.Cookie // Get all response cookies + Failed() bool // Check if the status code is not in the 2xx range + Header(name string) string // Get the value of a specific header + Headers() http.Header // Get all response headers + Json() (map[string]any, error) // Decode the response body as JSON into a map + Redirect() bool // Check if the response is a redirect (3xx status code) + ServerError() bool // Check if the status code is in the 5xx range + Status() int // Get the HTTP status code + Successful() bool // Check if the status code is in the 2xx range + + /* status code related methods */ + + OK() bool // 200 OK + Created() bool // 201 Created + Accepted() bool // 202 Accepted + NoContent() bool // 204 No Content + MovedPermanently() bool // 301 Moved Permanently + Found() bool // 302 Found + BadRequest() bool // 400 Bad Request + Unauthorized() bool // 401 Unauthorized + PaymentRequired() bool // 402 Payment Required + Forbidden() bool // 403 Forbidden + NotFound() bool // 404 Not Found + RequestTimeout() bool // 408 Request Timeout + Conflict() bool // 409 Conflict + UnprocessableEntity() bool // 422 Unprocessable Entity + TooManyRequests() bool // 429 Too Many Requests +} +``` + +### URI Templates + +URI Templates let you build dynamic request URLs using placeholders. +You can define these placeholders in your URL and then provide the values to replace them before making the request. +To achieve this, you can use `WithUrlParameter` for single parameters or `WithUrlParameters` for multiple parameters. + +```go +response, err := facades.Http(). + WithUrlParameter("id", "123"). + Get("https://api.example.com/users/{id}") + +// or + +response, err := facades.Http(). + WithUrlParameters(map[string]string{ + "bookId": "456", + "chapterNumber": "7", + }). + Get("https://api.example.com/books/{bookId}/chapters/{chapterNumber}") +``` + +### Request Query Parameters + +Add query parameters to your requests using `WithQueryParameter` for single parameters or +`WithQueryParameters` for multiple parameters via a map. + +```go +response1, err1 := facades.Http(). + WithQueryParameter("sort", "name"). + Get("https://api.example.com/users") +// Resulting URL: https://api.example.com/users?sort=name + +// or multiple query parameters +response2, err2 := facades.Http(). + WithQueryParameters(map[string]string{ + "page": "2", + "pageSize": "10", + }). + Get("https://api.example.com/products") +// Resulting URL: https://api.example.com/products?page=2&pageSize=10 +``` + +You can also add query parameters directly as a formatted string using `WithQueryString`: + +```go +response, err := facades.Http(). + WithQueryString("filter=active&order=price"). + Get("https://api.example.com/items") +``` + +### Sending a Request Body + +For HTTP verbs like `POST`, `PUT`, `PATCH` and `DELETE` accept `io.Reader` as the second argument. +To simplify building payloads, the framework provides utility methods for constructing request bodies. + +```go +import "github.com/goravel/framework/support/http" + +builder := http.NewBody().SetField("name", "krishan") + +body, err := builder.Build() + +response, err := facades.Http().WithHeader("Content-Type", body.ContentType()).Post("https://example.com/users", body.Reader()) +``` + +### Headers + +You can add headers to your requests using `WithHeader` for a single header +or `WithHeaders` for multiple headers provided as a map. + +```go +response, err := facades.Http(). + WithHeader("X-Custom-Header", "value"). + Get("https://api.example.com") + +// Add multiple headers +response, err = facades.Http(). + WithHeaders( map[string]string{ + "Content-Type": "application/json", + "Accept": "application/xml", + }). + Get("https://api.example.com") +``` + +You may use the `Accept` method to specify the content type that your application is expecting in response to your request: + +```go +response, err := facades.Http(). + Accept("application/xml"). + Get("https://api.example.com") +``` + +For convenience, you can use `AcceptJson` to quickly specify that you expect the API response to be in `application/json` format: + +```go +response, err := facades.Http(). + AcceptJson(). + Get("https://api.example.com/data") +``` + +To replace all existing headers with a new set, use `ReplaceHeaders`: + +```go +response, err := facades.Http(). + ReplaceHeaders(map[string]string{ + "Authorization": "Bearer token", + }). + Get("https://api.example.com") +``` + +You can remove a specific header using `WithoutHeader` or clear all headers with `FlushHeaders`. + +```go +response, err := facades.Http(). + WithoutHeader("X-Previous-Header"). + Get("https://api.example.com") + +// flush all headers +response, err := facades.Http(). + FlushHeaders(). + Get("https://api.example.com") +``` + +### Authentication + +You can specify basic authentication using the `WithBasicAuth` method: + +```go +response, err := facades.Http(). + WithBasicAuth("username", "password"). + Get("https://api.example.com/protected") +``` + +#### Bearer Tokens + +To quickly add a bearer token to the request's `Authorization` header, +you can use the `WithToken` method: + +```go +response, err := facades.Http(). + WithToken("your_bearer_token"). + Get("https://api.example.com/api/resource") +``` + +:::tip +The `WithToken` method also accepts an optional second argument to specify the token type (e.g., "Bearer", "Token"). +If no type is provided, it defaults to "Bearer". + +```go +response, err := facades.Http(). + WithToken("custom_token", "Token"). + Get("https://api.example.com/api/resource") +``` + +::: + +To remove the bearer token from the request, use the `WithoutToken` method: + +```go +response, err := facades.Http(). + WithoutToken(). + Get("https://api.example.com/api/resource") +``` + +### Context + +You can use `WithContext` to make your HTTP requests context-aware. +This allows you to control the lifecycle of a request, for instance, by setting timeouts or enabling cancellation. + +```go +ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) +defer cancel() + +response, err := facades.Http().WithContext(ctx).Get("https://example.com") +``` + +### Bind Response + +You can use the `Bind` method to specify the struct that the response should be bound to. + +```go +type User struct { + ID int `json:"id"` + Name string `json:"name"` +} + +func main() { + var user User + response, err := facades.Http().AcceptJson().Get("https://jsonplaceholder.typicode.com/users/1") + if err != nil { + fmt.Println("Error making request:", err) + return + } + + err = response.Bind(&user) + if err != nil { + fmt.Println("Error binding response:", err) + return + } + + fmt.Printf("User ID: %d, Name: %s\n", user.ID, user.Name) +} +``` + +### Cookie + +To send cookies with your HTTP requests, you can use `WithCookie` for a single cookie or `WithCookies` for multiple cookies. + +```go +response, err := facades.Http(). + WithCookie(&http.Cookie{Name: "user_id", Value: "123"}). + Get("https://example.com/profile") + +// multiple cookies +response, err := facades.Http(). + WithCookies([]*http.Cookie{ + {Name: "session_token", Value: "xyz"}, + {Name: "language", Value: "en"}, + }). + Get("https://example.com/dashboard") +``` + +To prevent specific cookies from being sent with your request, you can use `WithoutCookie`. + +```go +response, err := facades.Http(). + WithoutCookie("language"). + Get("https://example.com") +``` + +## Testing + +When testing your application, you often want to avoid making real network requests to external APIs. Whether it's to +speed up tests, avoid rate limits, or simulate failure scenarios, Goravel makes this easy. The `Http` facade provides a +powerful `Fake` method that allows you to instruct the HTTP client to return stubbed (dummy) responses when requests are made. + +### Faking Responses + +To start faking requests, pass a map to the `Fake` method. The keys represent the URL patterns or client names +you want to intercept, and the values represent the responses to return. You can use `*` as a wildcard character. + +The `Http` facade provides a convenient `Response` builder to construct various types of fake responses. + +```go +facades.Http().Fake(map[string]any{ + // Stub a specific URL + "https://github.com/goravel/framework": facades.Http().Response().Json(200, map[string]string{"foo": "bar"}), + + // Stub a wildcard pattern + "https://google.com/*": facades.Http().Response().String(200, "Hello World"), + + // Stub a specific Client (defined in config/http.go) + "github": facades.Http().Response().OK(), +}) +``` + +**Fallback URLs** + +Any request that does not match a pattern defined in `Fake` will be executed normally over the network. To prevent this, +you can define a fallback pattern using the single `*` wildcard, which will match all unmatched URLs. + +```go +facades.Http().Fake(map[string]any{ + "https://github.com/*": facades.Http().Response().Json(200, map[string]string{"id": "1"}), + "*": facades.Http().Response().Status(404), +}) +``` + +**Implicit Conversions** + +For convenience, you do not always need to use the `Response` builder. You can pass simple `int`, `string`, or `map` +values, and Goravel will automatically convert them into responses. + +```go +facades.Http().Fake(map[string]any{ + "https://goravel.dev/*": "Hello World", // String -> 200 OK with body + "https://github.com/*": map[string]string{"a": "b"}, // Map -> 200 OK JSON + "https://stripe.com/*": 500, // Int -> Status code only +}) +``` + +### Fake Response Builder + +The `facades.Http().Response()` method provides a fluent interface to build custom responses easily. + +```go +// Create a response using a file content +facades.Http().Response().File(200, "./tests/fixtures/user.json") + +// Create a JSON response +facades.Http().Response().Json(201, map[string]any{"created": true}) + +// Create a response with custom headers +headers := http.Header{} +headers.Add("X-Custom", "Value") +facades.Http().Response().Make(200, "Body Content", headers) + +// Standard status helpers +facades.Http().Response().OK() +facades.Http().Response().Status(403) +``` + +### Faking Response Sequences + +Sometimes you may need to specify that a single URL should return a series of different responses in order, +such as when testing retries or rate-limiting logic. You can use the `Sequence` method to build this flow. + +```go +facades.Http().Fake(map[string]any{ + "github": facades.Http().Sequence(). + PushStatus(500). // 1st Request: Server Error + PushString(429, "Rate Limit"). // 2nd Request: Rate Limit + PushStatus(200), // 3rd Request: Success +}) +``` + +**Empty Sequences** + +When all responses in a sequence have been consumed, any further requests will cause the client to return an error. +If you wish to specify a default response instead of failing, use the `WhenEmpty` method: + +```go +facades.Http().Fake(map[string]any{ + "github": facades.Http().Sequence(). + PushStatus(200). + WhenEmpty(facades.Http().Response().Status(404)), +}) +``` + +### Inspecting Requests + +When faking responses, it is crucial to verify that the correct requests were actually sent by your application. +You can use the `AssertSent` method to inspect the request and return a boolean indicating if it matches your expectations. + +```go +facades.Http().AssertSent(func(req client.Request) bool { + return req.Url() == "https://api.example.com/users" && + req.Method() == "POST" && + req.Input("role") == "admin" && + req.Header("Authorization") != "" +}) +``` + +**Other Assertions** + +You can also assert that a specific request was _not_ sent, or check the total number of requests sent: + +```go +// Assert a request was NOT sent +facades.Http().AssertNotSent(func(req client.Request) bool { + return req.Url() == "https://api.example.com/legacy-endpoint" +}) + +// Assert that no requests were sent at all +facades.Http().AssertNothingSent() + +// Assert that exactly 3 requests were sent +facades.Http().AssertSentCount(3) +``` + +### Preventing Stray Requests + +To ensure your tests are strictly isolated and do not accidentally hit real external APIs, you can use the +`PreventStrayRequests` method. After calling this, any request that does not match a defined Fake rule will cause the +test to panic with an exception. + +```go +facades.Http().Fake(map[string]any{ + "github": facades.Http().Response().OK(), +}).PreventStrayRequests() + +// This request is mocked and succeeds +facades.Http().Client("github").Get("/") + +// This request is NOT mocked and will panic +facades.Http().Get("https://google.com") +``` + +**Allowing Specific Strays** + +If you need to block most requests but allow specific internal services (like a local test server), +you can use `AllowStrayRequests`: + +```go +facades.Http().PreventStrayRequests().AllowStrayRequests([]string{ + "http://localhost:8080/*", +}) +``` + +### Resetting State + +The `Http` facade is a singleton, meaning mocked responses persist across the entire runtime of your test suite unless +cleared. To avoid "leaking" mocks from one test to another, you should strictly use the `Reset` method in +your test cleanup or setup. + +```go +func TestExternalApi(t *testing.T) { + defer facades.Http().Reset() + + facades.Http().Fake(nil) + + // ... assertions +} +``` + +:::warning Global State & Parallel Testing +The `Fake` and `Reset` methods mutate the global state of the HTTP client factory. Because of this, **you should avoid +running tests that mock the HTTP client in parallel** (using `t.Parallel()`). Doing so may result in race conditions +where one test resets the mocks while another is still running. +::: + + From bb7f2d0922faad759253f31bbc6b6ab2036e7345 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:15 +0800 Subject: [PATCH 017/163] New translations localization.md (Uzbek) [skip ci] Update translations (Uzbek) localization.md --- uz_UZ/digging-deeper/localization.md | 187 +++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 uz_UZ/digging-deeper/localization.md diff --git a/uz_UZ/digging-deeper/localization.md b/uz_UZ/digging-deeper/localization.md new file mode 100644 index 000000000..53b8a335e --- /dev/null +++ b/uz_UZ/digging-deeper/localization.md @@ -0,0 +1,187 @@ +# Localization + +[[toc]] + +## Introduction + +Goravel's localization features provide a convenient way to retrieve strings in various languages, making it easy to support multiple languages in your application. Language strings are stored in files in the `lang` directory, and Goravel supports two ways to organize language files: + +Each language has its own file: + +``` +/lang + en.json + cn.json +``` + +Or, when there are too many translations, they can be categorized: + +``` +/lang + /en + user.json + /cn + user.json +``` + +## Configuring the Locale + +The default language of the application is stored in the `locale` configuration option in the `config/app.go` configuration file. You can modify this value as needed to suit your application's requirements. + +You can also use the `SetLocale` method provided by the App Facade to modify the default language for a single `HTTP` request at runtime: + +```go +facades.Route().Get("/", func(ctx http.Context) http.Response { + facades.App().SetLocale(ctx, "en") + + return ctx.Response() +}) +``` + +You can configure a "fallback locale" that will be used when the current language does not contain the given translation string. Like the default language, the fallback language is also configured in the `config/app.go` configuration file. + +``` +"fallback_locale": "en", +``` + +### Determining the Current Locale + +You can use the `CurrentLocale` and `IsLocale` methods to determine the current `locale` or check if the `locale` is a given value. + +``` +locale := facades.App().CurrentLocale(ctx) +if facades.App().IsLocale(ctx, "en") {} +``` + +### Defining Translation Strings + +In language files, you can define single-level or multi-level structures: + +```json +// lang/en.json +{ + "name": "It's your name", + "required": { + "user_id": "UserID is required" + } +} +``` + +### Retrieving Translation Strings + +You can use the `facades.Lang(ctx).Get()` method to retrieve translation strings from language files. If the language file contains multiple levels, you can use `.` to connect them, and if the language file is in multiple levels of folders, you can use `/` to connect them. + +For example: + +``` +// lang/en.json +{ + "name": "It's your name", + "required": { + "user_id": "UserID is required" + } +} + +facades.Lang(ctx).Get("name") +facades.Lang(ctx).Get("required.user_id") + +// lang/en/role/user.json +{ + "name": "It's your name", + "required": { + "user_id": "UserID is required" + } +} + +facades.Lang(ctx).Get("role/user.name") +facades.Lang(ctx).Get("role/user.required.user_id") +``` + +#### Replacing Parameters in Translation Strings + +You can define placeholders in translation strings. All placeholders have the prefix `:`. For example, you can use a placeholder to define a welcome message: + +```json +{ + "welcome": "Welcome, :name" +} +``` + +To replace placeholders when retrieving a translation string, you can pass a translation option with the replacement map as the second parameter to the `facades.Lang(ctx).Get()` method: + +```go +facades.Lang(ctx).Get("welcome", translation.Option{ + Replace: map[string]string{ + "name": "Goravel", + }, +}) +``` + +#### Pluralization + +Pluralization is a complex problem because different languages have various pluralization rules. However, Goravel can help you translate strings based on the pluralization rules you define. By using the `|` character, you can differentiate between the singular and plural forms of a string: + +```json +{ + "apples": "There is one apple|There are many apples" +} +``` + +You can even create more complex pluralization rules by specifying translation strings for multiple value ranges: + +```json +{ + "apples": "{0} There are none|[1,19] There are some|[20,*] There are many" +} +``` + +After defining a translation string with pluralization options, you can use the `facades.Lang(ctx).Choice()` method to retrieve the line for a given `count`. In this example, because the count is greater than 1, the plural form of the translation string is returned: + +```go +facades.Lang(ctx).Choice("messages.apples", 10) +``` + +You can also define placeholder attributes in pluralization strings. By passing an array as the third parameter to the `facades.Lang(ctx).Choice()` method, you can replace these placeholders: + +``` +"minutes_ago": "{1} :value minute ago|[2,*] :value minutes ago", + +facades.Lang(ctx).Choice("time.minutes_ago", 5, translation.Option{ + Replace: map[string]string{ + "value": "5", + }, +}) +``` + +## Embed Loading + +When using embed loading, the language files will be compiled into the binary file and no longer need to be deployed. The independent language files and embed loading can be used at the same time, just configure `lang_path` and `lang_fs` in the `config/app.go` file. When using, the independent language file mode will be used first, and when the independent language file does not exist, the embed loading will be used. + +In the same directory as the language files, create a `fs.go` file: + +``` +/lang + en.json + cn.json + fs.go +``` + +```go +// lang/fs.go +package lang + +import "embed" + +//go:embed * +var FS embed.FS +``` + +Then configure in the `config/app.go` file: + +```go +// config/app.go +import "lang" + +"lang_path": "lang", +"lang_fs": lang.Fs, +``` From cb543bd511125860d5d1da0c8ce2852a67c2084a Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:16 +0800 Subject: [PATCH 018/163] New translations mail.md (Uzbek) [skip ci] Update translations (Uzbek) mail.md --- uz_UZ/digging-deeper/mail.md | 200 +++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 uz_UZ/digging-deeper/mail.md diff --git a/uz_UZ/digging-deeper/mail.md b/uz_UZ/digging-deeper/mail.md new file mode 100644 index 000000000..d4b9937dd --- /dev/null +++ b/uz_UZ/digging-deeper/mail.md @@ -0,0 +1,200 @@ +# Mail + +[[toc]] + +## Introduction + +Goravel can use `facades.Mail()` to easily send mail locally. + +## Configuration + +Before sending an email, you need to configure the `config/mail.go` configuration file. + +## Send Mail + +```go +import "github.com/goravel/framework/mail" + +err := facades.Mail().To([]string{"example@example.com"}). + Cc([]string{"example@example.com"}). + Bcc([]string{"example@example.com"}). + Attach([]string{"file.png"}). + Content(mail.Html("

Hello Goravel

")). + Headers(map[string]string{"X-Mailer": "Goravel"}). + Subject("Subject"). + Send() +``` + +## Send Mail By Queue + +```go +import "github.com/goravel/framework/mail" + +err := facades.Mail().To([]string{"example@example.com"}). + Cc([]string{"example@example.com"}). + Bcc([]string{"example@example.com"}). + Attach([]string{"file.png"}). + Content(mail.Html("

Hello Goravel

")). + Headers(map[string]string{"X-Mailer": "Goravel"}). + Subject("Subject"). + Queue() +``` + +You can also customize the queue: + +```go +import "github.com/goravel/framework/mail" + +err := facades.Mail().To([]string{"example@example.com"}). + Cc([]string{"example@example.com"}). + Bcc([]string{"example@example.com"}). + Attach([]string{"file.png"}). + Content(mail.Html("

Hello Goravel

")). + Subject("Subject"). + Headers(map[string]string{"X-Mailer": "Goravel"}). + Queue(mail.Queue().Connection("redis").Queue("mail")) +``` + +## Setting Sender + +Framework uses `MAIL_FROM_ ADDRESS` and `MAIL_FROM_ NAME` in the `config/mail.go` configuration file as global senders. You can also customize the sender, but you need to note that the mail address needs to be consistent with the configured STMP: + +```go +import "github.com/goravel/framework/mail" + +err := facades.Mail().To([]string{"example@example.com"}). + From(mail.Address(testFromAddress, testFromName)). + Cc([]string{"example@example.com"}). + Bcc([]string{"example@example.com"}). + Attach([]string{"file.png"}). + Content(mail.Html("

Hello Goravel

")). + Headers(map[string]string{"X-Mailer": "Goravel"}). + Subject("Subject"). + Queue(mail.Queue().Connection("redis").Queue("mail")) +``` + +## Using Mailable + +The parameters of the email can be set in a `Mailable` struct. These structs are stored in the `app/mails` directory. You can quickly create a `Mailable` using the `make:mail` Artisan command: + +```bash +go run . artisan make:mail OrderShipped +``` + +The generated `OrderShipped` struct is as follows: + +```go +import "github.com/goravel/framework/contracts/mail" + +type OrderShipped struct { +} + +func NewOrderShipped() *OrderShipped { + return &OrderShipped{} +} + +func (m *OrderShipped) Headers() map[string]string { + return map[string]string{ + "X-Mailer": "goravel", + } +} + +func (m *OrderShipped) Attachments() []string { + return []string{"../logo.png"} +} + +func (m *OrderShipped) Content() *mail.Content { + return &mail.Content{Html: "

Hello Goravel

"} +} + +func (m *OrderShipped) Envelope() *mail.Envelope { + return &mail.Envelope{ + Bcc: []string{"bcc@goravel.dev"}, + Cc: []string{"cc@goravel.dev"}, + From: mail.From{Address: "from@goravel.dev", Name: "from"}, + Subject: "Goravel", + To: []string{"to@goravel.dev"}, + } +} + +func (m *OrderShipped) Queue() *mail.Queue { + return &mail.Queue{ + Connection: "redis", + Queue: "mail", + } +} +``` + +Then you can use the `Mailalbe` in the `Send` and `Queue` methods: + +```go +err := facades.Mail().Send(mails.NewOrderShipped()) +err := facades.Mail().Queue(mails.NewOrderShipped()) +``` + +## Using Template + +The mail module now supports using templates directly with the `html/template` engine. This allows you to render email templates with dynamic data. + +### Configuration + +To enable template support, configure the `config/mail.go` file: + +```go +"template": map[string]any{ + "default": config.Env("MAIL_TEMPLATE_ENGINE", "html"), + "engines": map[string]any{ + "html": map[string]any{ + "driver": "html", + "path": config.Env("MAIL_VIEWS_PATH", "resources/views/mail"), + }, + }, +} +``` + +### Creating Templates + +Create your email templates in the specified views directory. For example: + +```html + +

Welcome {{.Name}}!

+

Thank you for joining {{.AppName}}.

+``` + +### Sending Emails with Templates + +You can use the `Content` method to specify the template and pass dynamic data: + +```go +facades.Mail(). + To([]string{"user@example.com"}). + Subject("Welcome"). + Content(mail.Content{ + View: "welcome.tmpl", + With: map[string]any{ + "Name": "John", + "AppName": "Goravel", + }, + }). + Send() +``` + +### Custom Template Engines + +You can also register custom template engines in the configuration: + +```go +"template": map[string]any{ + "default": "blade", + "engines": map[string]any{ + "blade": map[string]any{ + "driver": "custom", + "via": func() (mail.Template, error) { + return NewBladeTemplateEngine(), nil + }, + }, + }, +} +``` + From 3c98f99973ffffc5fe3617eb830c206d64150d1b Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:18 +0800 Subject: [PATCH 019/163] New translations package-development.md (Uzbek) [skip ci] Update translations (Uzbek) package-development.md --- uz_UZ/digging-deeper/package-development.md | 185 ++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 uz_UZ/digging-deeper/package-development.md diff --git a/uz_UZ/digging-deeper/package-development.md b/uz_UZ/digging-deeper/package-development.md new file mode 100644 index 000000000..3771bc728 --- /dev/null +++ b/uz_UZ/digging-deeper/package-development.md @@ -0,0 +1,185 @@ +# Package Development + +[[toc]] + +## Introduction + +Packages are the primary way of adding functionality to Goravel. These packages may contain routes, controllers, and configurations that are specifically designed to enhance a Goravel application. This guide focuses on developing Goravel-specific packages. + +Here is an example for building a third-party package: [goravel/example-package](https://github.com/goravel/example-package) + +## Creating A Package + +You can use easily create a package template using the Artisan command: + +```shell +./artisan make:package sms +``` + +The created files are saved by default in the root `packages` folder, you can use `--root` option to customize: + +```shell +./artisan make:package --root=pkg sms +``` + +## Service Providers + +[Service providers](../architecture-concepts/service-providers.md) act as the bridge between your package and Goravel. They are typically located in the root of the package as a `service_provider.go` file. Their main function is to bind items into Goravel's service container and guide Goravel in loading package resources. + +## Install The Package + +When creating a package, if it contains a `setup/setup.go` file, you can define the package installation logic in this file, and then users can use the `package:install` command to install the package: + +```shell +./artisan package:install github.com/goravel/example-package +``` + +The following is an explanation of the installation process defined in the `setup/setup.go` file, which helps you write your own package installation logic: + +```go +// setup/setup.go +package main + +import ( + "os" + + "github.com/goravel/framework/packages" + "github.com/goravel/framework/packages/modify" + "github.com/goravel/framework/support/file" + "github.com/goravel/framework/support/path" +) + +func main() { + // Initialize setup to get paths, this should be called at the beginning. + setup := packages.Setup(os.Args) + + // The config file will be published to the project's config directory automatically when installing by this way. + // You can also publish this config file manually: ./artisan vendor:publish --package=github.com/goravel/example-package + config, err := file.GetPackageContent(setup.Paths().Module().String(), "setup/config/hello.go") + if err != nil { + panic(err) + } + + serviceProvider := "&hello.ServiceProvider{}" + moduleImport := setup.Paths().Module().Import() + + setup.Install( + // Register the service provider to the providers slice in bootstrap/providers.go + modify.RegisterProvider(moduleImport, serviceProvider), + + // Add the config file to the config directory + modify.File(path.Config("hello.go")).Overwrite(config), + ).Uninstall( + // Remove the config file from the config directory + modify.File(path.Config("hello.go")).Remove(), + + // Unregister the service provider from the providers slice in bootstrap/providers.go + modify.UnregisterProvider(moduleImport, serviceProvider), + ).Execute() +} +``` + +## Resources + +### Configuration + +Typically, you will need to publish your package's configuration file to the application's `config` directory. This will allow users of your package to easily override your default configuration options. To allow your configuration files to be published, call the `Publishes` method from the `Boot` method of your service provider, the first parameter is the package name, and the second parameter is the mapping between the current package file path and the project path: + +```go +func (receiver *ServiceProvider) Boot(app foundation.Application) { + app.Publishes("github.com/goravel/example-package", map[string]string{ + "config/sms.go": app.ConfigPath("sms.go"), + }) +} +``` + +### Routes + +If there are [routes](../the-basics/routing.md) in your package, you can use `app.MakeRoute()` to resolve `facades.Route()`, then add the routes to the project: + +```go +func (receiver *ServiceProvider) Boot(app foundation.Application) { + route := app.MakeRoute() + route.Get("sms", ***) +} +``` + +### Migrations + +If there are [migrations](../database/migrations.md) in your package, you can publish them by the `Publishes` method: + +```go +func (receiver *ServiceProvider) Boot(app foundation.Application) { + app.Publishes("github.com/goravel/example-package", map[string]string{ + "migrations": app.DatabasePath("migrations"), + }) +} +``` + +### Models + +If there are any new [models](../orm/getting-started.md) defined as part of your package, they can be published using the `Publishes` method: + +```go +func (receiver *ServiceProvider) Boot(app foundation.Application) { + app.Publishes("github.com/goravel/example-package", map[string]string{ + "models": app.ModelPath("models"), + }) +} +``` + +## Commands + +You can register `Artisan` command by the `Commands` method, you can run the commands using [Artisan CLI](../digging-deeper/artisan-console.md) after registering them. + +```go +func (receiver *ServiceProvider) Boot(app foundation.Application) { + app.Commands([]console.Command{ + commands.NewSmsCommand(), + }) +} +``` + +## Public Assets + +Your package may have assets such as JavaScript, CSS, and images. To publish these assets to the application's `public` directory, use the service provider's `Publishes` method: + +```go +func (receiver *ServiceProvider) Boot(app foundation.Application) { + app.Publishes("github.com/goravel/example-package", map[string]string{ + "public": app.PublicPath("vendor"), + }) +} +``` + +## Publishing File Groups + +If you want to publish specific groups of package assets and resources separately, you can use tags when calling the `Publishes` method from the package's service provider. This allows you to give users the option to publish certain files, like configuration files, without having to publish all the package's assets. To illustrate, you can define two publish groups for the `sms` package (`sms-config` and `sms-migrations`) using tags in the `Boot` method of the package's service provider. + +```go +func (receiver *ServiceProvider) Boot(app foundation.Application) { + app.Publishes("github.com/goravel/example-package", map[string]string{ + "config/sms.go": app.ConfigPath("sms.go"), + }, "sms-config") + app.Publishes("github.com/goravel/example-package", map[string]string{ + "migrations": app.DatabasePath("migrations"), + }, "sms-migrations") +} +``` + +## Publish Resources + +In the project, You can publish the resources registered in a package using `vendor:publish` Artisan command: + +```shell +./artisan vendor:publish --package={You package name} +``` + +The command can use the following options: + +| Option Name | Alias | Action | +| ----------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| --package | -p | Package name, can be a remote package: `github.com/goravel/example-package`, and also can be a local package: `./packages/example-package`, note that when using a local package name, it needs to start with `./`. | +| --tag | -t | Resource Group | +| --force | -f | Overwrite any existing files | +| --existing | -e | Publish and overwrite only the files that have already been published | From 8409dbdceaec49a00f62dcd9ad8512a23ea460cd Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:19 +0800 Subject: [PATCH 020/163] New translations queues.md (Uzbek) [skip ci] Update translations (Uzbek) queues.md --- uz_UZ/digging-deeper/queues.md | 304 +++++++++++++++++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 uz_UZ/digging-deeper/queues.md diff --git a/uz_UZ/digging-deeper/queues.md b/uz_UZ/digging-deeper/queues.md new file mode 100644 index 000000000..791d13655 --- /dev/null +++ b/uz_UZ/digging-deeper/queues.md @@ -0,0 +1,304 @@ +# Queues + +[[toc]] + +## Introduction + +When building your web application, there may be tasks, like parsing and storing an uploaded CSV file, that take too long to complete during a web request. Fortunately, Goravel offers a solution by allowing you to create queued jobs that can run in the background. This way, by moving time-intensive tasks to a queue, your application can respond to web requests much faster and provide a better user experience for your customers. To implement this feature, we use `facades.Queue()`. + +### Connections Vs. Queues + +Before delving into Goravel queues, it's important to understand the difference between "connections" and "queues". In the configuration file, `config/queue.go`, you'll find an array for `connections` configuration. This option specifies the connections to backend queue services like Redis. However, every queue connection can have multiple "queues", which can be thought of as different stacks or piles of queued jobs. + +It's essential to note that each connection configuration example in the queue configuration file includes a `queue` attribute. This attribute is the default queue to which jobs will be dispatched when they are sent to a given connection. In simpler terms, if you dispatch a job without explicitly defining which queue it should be dispatched to, the job will be placed in the queue defined in the queue attribute of the connection configuration. + +```go +// This job is sent to the default connection's default queue +err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{ + {Type: "int", Value: 1}, +}).Dispatch() + +// This job is sent to the default connection's "emails" queue +err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{ + {Type: "int", Value: 1}, +}).OnQueue("emails").Dispatch() +``` + +## Driver + +The queue configuration file is stored in `config/queue.go`, and different queue drivers can be set in the configuration file. + +### Sync Driver + +The sync driver is the default driver, it will not push tasks to the queue, but execute directly in the current process. + +### Database Driver + +To use the `database` driver, you need to create a database table to store tasks first: [20210101000002_create_jobs_table.go](https://github.com/goravel/goravel/blob/master/database/migrations/20210101000002_create_jobs_table.go). The migration file is located in the `database/migrations` directory by default. + +### Custom Driver + +If the current driver cannot meet your needs, you can customize the driver. You need to implement the [Driver](https://github.com/goravel/framework/blob/master/contracts/queue/driver.go#L14) interface in `contracts/queue/driver.go`. + +The official implementation of the `Redis` driver, you can refer to [Redis Driver](https://github.com/goravel/redis) to implement your own custom driver. + +After implementing the custom driver, you can add the configuration to `config/queue.go`: + +``` +... +"connections": map[string]any{ + "redis": map[string]any{ + "driver": "custom", + "connection": "default", + "queue": "default", + "via": func() (queue.Driver, error) { + return redisfacades.Queue("redis") // The redis value is the key of connections + }, + }, +}, +``` + +## Creating Jobs + +### Generating Job Classes + +By default, all of the jobs for your application are stored in the `app/jobs` directory. If the `app/Jobs` directory doesn't exist, it will be created when you run the `make:job` Artisan command: + +```shell +./artisan make:job ProcessPodcast +./artisan make:job user/ProcessPodcast +``` + +### Register Jobs + +A new job created by `make:job` will be registered automatically in the `bootstrap/jobs.go::Jobs()` function and the function will be called by `WithJobs`. You need register the job manually if you create the job file by yourself. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithJobs(Jobs). + WithConfig(config.Boot). + Create() +} +``` + +### Class Structure + +Job classes are very simple, consisting of two methods: `Signature` and `Handle`. `Signature` serves as a task's distinct identifier, while `Handle` executes when the queue processes the task. Additionally, the `[]queue.Arg{}` passed when the task executes will be transmitted into `Handle`: + +```go +package jobs + +type ProcessPodcast struct { +} + +// Signature The name and signature of the job. +func (r *ProcessPodcast) Signature() string { + return "process_podcast" +} + +// Handle Execute the job. +func (r *ProcessPodcast) Handle(args ...any) error { + return nil +} +``` + +#### Job Retry + +Job classes support an optional `ShouldRetry(err error, attempt int) (retryable bool, delay time.Duration)` method, which is used to control job retry. + +```go +// ShouldRetry determines if the job should be retried based on the error. +func (r *ProcessPodcast) ShouldRetry(err error, attempt int) (retryable bool, delay time.Duration) { + return true, 10 * time.Second +} +``` + +## Start Queue Server + +The default queue worker will be run by the runner of queue seriver provider, if you want to start multiple queue workers with different configuration, you can create [a runner](../architecture-concepts/service-providers.md#runners) and add it to the `WithRunners` function in the `bootstrap/app.go` file: + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithConfig(config.Boot). + WithRunners(func() []contractsfoundation.Runner { + return []contractsfoundation.Runner{ + YourRunner, + } + }). + Create() +} +``` + +You can check [the default queue runner](https://github.com/goravel/framework/blob/master/queue/runners.go) for reference. + +## Dispatching Jobs + +Once you have written the job class, you can dispatch it using the `Dispatch` method on the job itself: + +```go +package controllers + +import ( + "github.com/goravel/framework/contracts/queue" + "github.com/goravel/framework/contracts/http" + + "goravel/app/facades" + "goravel/app/jobs" +) + +type UserController struct { +} + +func (r *UserController) Show(ctx http.Context) { + err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{}).Dispatch() + if err != nil { + // do something + } +} +``` + +### Synchronous Dispatching + +If you want to dispatch a job immediately (synchronously), you can use the `DispatchSync` method. When using this method, the job will not be queued and will be executed immediately within the current process: + +```go +package controllers + +import ( + "github.com/goravel/framework/contracts/queue" + "github.com/goravel/framework/contracts/http" + + "goravel/app/facades" + "goravel/app/jobs" +) + +type UserController struct { +} + +func (r *UserController) Show(ctx http.Context) { + err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{}).DispatchSync() + if err != nil { + // do something + } +} +``` + +### Job Chaining + +Job chaining allows you to specify a list of queued jobs to be executed in a specific order. If any job in the sequence fails, the rest of the jobs will not be executed. To run a queued job chain, you can use the `Chain` method provided by the `facades.Queue()`: + +```go +err := facades.Queue().Chain([]queue.Jobs{ + { + Job: &jobs.Test{}, + Args: []queue.Arg{ + {Type: "int", Value: 1}, + }, + }, + { + Job: &jobs.Test1{}, + Args: []queue.Arg{ + {Type: "int", Value: 2}, + }, + }, +}).Dispatch() +``` + +### Delayed Dispatching + +If you would like to specify that a job should not be immediately processed by a queue worker, you may use the `Delay` method during job dispatch. For example, let's specify that a job should not be available for processing after 100 seconds of dispatching: + +```go +err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{}).Delay(time.Now().Add(100*time.Second)).Dispatch() +``` + +### Customizing The Queue & Connection + +#### Dispatching To A Particular Queue + +By pushing jobs to different queues, you may "categorize" your queued jobs and even prioritize how many workers you assign to various queues. + +```go +err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{}).OnQueue("processing").Dispatch() +``` + +#### Dispatching To A Particular Connection + +If your application interacts with multiple queue connections, you can use the `OnConnection` method to specify the connection to which the task is pushed. + +```go +err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{}).OnConnection("sync").Dispatch() +``` + +You may chain the `OnConnection` and `OnQueue` methods together to specify the connection and the queue for a job: + +```go +err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{}).OnConnection("sync").OnQueue("processing").Dispatch() +``` + +## View Failed Jobs + +You can use the `queue:failed` command to view failed jobs, this command will get the failed jobs from the `failed_jobs` table in the database: + +```shell +./artisan queue:failed +``` + +## Retrying Failed Jobs + +If a job fails during processing, you can use the `queue:retry` command to retry the job. Before retrying the job, you need to get the UUID of the job to be retried from the `failed_jobs` table in the database: + +```shell +# Retry a single job +./artisan queue:retry 4427387e-c75a-4295-afb3-2f3d0e410494 + +# Retry multiple jobs +./artisan queue:retry 4427387e-c75a-4295-afb3-2f3d0e410494 eafdd963-a8b7-4aca-9421-b376ed9f4382 + +# Retry failed jobs for a specific connection +./artisan queue:retry --connection=redis + +# Retry failed jobs for a specific queue +./artisan queue:retry --queue=processing + +# Retry failed jobs for a specific connection and queue +./artisan queue:retry --connection=redis --queue=processing + +# Retry all failed jobs +./artisan queue:retry all +``` + +## `queue.Arg.Type` Supported Types + +```go +bool +int +int8 +int16 +int32 +int64 +uint +uint8 +uint16 +uint32 +uint64 +float32 +float64 +string +[]bool +[]int +[]int8 +[]int16 +[]int32 +[]int64 +[]uint +[]uint8 +[]uint16 +[]uint32 +[]uint64 +[]float32 +[]float64 +[]string +``` From 9a3b96ec916ac98b3a38b1f85c7215a8b01cebbf Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:21 +0800 Subject: [PATCH 021/163] New translations strings.md (Uzbek) [skip ci] Update translations (Uzbek) strings.md --- uz_UZ/digging-deeper/strings.md | 1075 +++++++++++++++++++++++++++++++ 1 file changed, 1075 insertions(+) create mode 100644 uz_UZ/digging-deeper/strings.md diff --git a/uz_UZ/digging-deeper/strings.md b/uz_UZ/digging-deeper/strings.md new file mode 100644 index 000000000..832da5e6d --- /dev/null +++ b/uz_UZ/digging-deeper/strings.md @@ -0,0 +1,1075 @@ +# Strings + +[[toc]] + +## Introduction + +Goravel provides a fluent string manipulation library that allows you to easily manipulate strings. Fluent Strings allows you to combine multiple string operations through method chaining, where most of the methods returns an instance of `support/str.String`, letting you chain additional methods. To get the final string value after applying the chained operations, you can call the `String` method, which returns the underlying `string` value. + +```go +import "github.com/goravel/framework/support/str" + +str.Of(" Goravel ").Trim().Lower().UpperFirst().String() // "Goravel" +``` + +## Available Methods + +### `Of` + +The `Of` method creates a new fluent string instance from a given string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel") +``` + +### `After` + +The `After` method returns the portion of a string that appears after a specified value. If the value is an empty string or does not exist within the original string, the full string is returned. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello World!").After("Hello").String() // " World!" +``` + +### `AfterLast` + +The `AfterLast` method returns the portion of a string that appears after the last occurrence of a specified value. If the value is an empty string or does not exist within the original string, the full string is returned. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("docs.goravel.dev").AfterLast(".").String() // "dev" +``` + +### `Append` + +The `Append` method appends the specified value to the end of the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Bowen").Append(" Han").String() // "Bowen Han" +``` + +### `Basename` + +The `Basename` method returns the trailing name component of a path, optionally removing a specified suffix from the base name. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("framework/support/str").Basename().String() // "str" + +str.Of("framework/support/str.go").Basename(".go").String() // "str" +``` + +### `Before` + +The `Before` method returns the portion of a string that appears before a specified value. If the value is an empty string or does not exist within the original string, the full string is returned. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello World!").Before("World").String() // "Hello " +``` + +### `BeforeLast` + +The `BeforeLast` method returns the portion of a string that appears before the last occurrence of a specified value. If the value is an empty string or does not exist within the original string, the full string is returned. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("docs.goravel.dev").BeforeLast(".").String() // "docs.goravel" +``` + +### `Between` + +The `Between` method returns the portion of a string between two given values. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("[Hello] World!").Between("[", "]").String() // "Hello" +``` + +### `BetweenFirst` + +The `BetweenFirst` method returns the portion of a string between the first occurrence of two given values. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("[Hello] [World]!").BetweenFirst("[", "]").String() // "Hello" +``` + +### `Camel` + +The `Camel` method converts the string to `camelCase`. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("hello_world").Camel().String() // "helloWorld" +``` + +### `CharAt` + +The `CharAt` method returns the character at the given index. If the index is out of bounds, an empty string will be returned. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").CharAt(1) // "o" +``` + +### `ChopEnd` + +The `ChopEnd` method removes the given value(s) from the end of the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("https://goravel.com").ChopEnd(".dev", ".com").String() // https://goravel +``` + +### `ChopStart` + +The `ChopStart` method removes the given value(s) from the start of the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("https://goravel.dev").ChopStart("http://", "https://").String() // goravel.dev +``` + +### `Contains` + +The `Contains` method determines if the given string contains the given value. The method is case-sensitive. If multiple values are provided, it will return `true` if the string contains any of the values. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").Contains("Gor") // true + +str.Of("Hello World").Contains("Gor", "Hello") // true +``` + +### `ContainsAll` + +The `ContainsAll` method determines if the given string contains all of the given values. The method is case-sensitive. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello World").ContainsAll("Hello", "World") // true + +str.Of("Hello World").ContainsAll("Hello", "Gor") // false +``` + +### `Dirname` + +The `Dirname` method returns the parent portion of a path. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("framework/support/str").Dirname().String() // "framework/support" +``` + +Optionally, you may provide the directory level to trim from the path. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("framework/support/str").Dirname(2).String() // "framework" +``` + +### `EndsWith` + +The `EndsWith` method determines if the given string ends with the given value. The method is case-sensitive. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").EndsWith("vel") // true +``` + +You may pass multiple values to the method to determine if the string ends with any of the values. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").EndsWith("vel", "lie") // true +``` + +### `Exactly` + +The `Exactly` method determines if the given string is exactly equal to the given value. The method is case-sensitive. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").Exactly("Goravel") // true +``` + +### `Except` + +The `Except` method extracts an excerpt from the string that matches the first occurrence of the given value. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("This is a beautiful morning"). + Excerpt("beautiful", str.ExcerptOption{ + Radius: 5, + }).String() // "...is a beautiful morn... +``` + +Additionally, you may use `Omission` option to change the string that is used to indicate the excerpt. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("This is a beautiful morning"). + Excerpt("beautiful", str.ExcerptOption{ + Radius: 5, + Omission: "(...)" + }).String() // "(...)is a beautiful morn(...)" +``` + +### `Explode` + +The `Explode` method splits the string into an array of strings using the given delimiter. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello World").Explode(" ") // []string{"Hello", "World"} +``` + +### `Finish` + +The `Finish` method ensures that the given string ends with the given value. If the string already ends with the value, it will not be added again. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("framework").Finish("/").String() // "framework/" + +str.Of("framework/").Finish("/").String() // "framework/" +``` + +### `Headline` + +The `Headline` method converts the string to a headline. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("bowen_han").Headline().String() // "Bowen Han" + +str.Of("HelloWorld").Headline().String() // "Hello World" +``` + +### `Is` + +The `Is` method determines if the given string matches the given pattern. The method is case-sensitive. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("foo123").Is("bar*", "baz*", "foo*") // true +``` + +### `IsEmpty` + +The `IsEmpty` method determines if the given string is empty. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("").IsEmpty() // true +``` + +### `IsNotEmpty` + +The `IsNotEmpty` method determines if the given string is not empty. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").IsNotEmpty() // true +``` + +### `IsAscii` + +The `IsAscii` method determines if the given string contains only ASCII characters. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").IsAscii() // true + +str.Of("你好").IsAscii() // false +``` + +### `IsSlice` + +The `IsSlice` method determines if the given string is a slice. + +```go +import "github.com/goravel/framework/support/str" + +str.Of(`[{"name": "John"}, {"name": "Alice"}]`).IsSlice() // true + +str.Of(`{"name": "John"}`).IsSlice() // false +``` + +### `IsMap` + +The `IsMap` method determines if the given string is a map. + +```go +import "github.com/goravel/framework/support/str" + +str.Of(`{"name": "John"}`).IsMap() // true + +str.Of(`[{"name": "John"}, {"name": "Alice"}]`).IsMap() // false +``` + +### `IsUlid` + +The `IsUlid` method determines if the given string is a ULID. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("01E5Z6Z1Z6Z1Z6Z1Z6Z1Z6Z1Z6").IsUlid() // true + +str.Of("krishan").IsUlid() // false +``` + +### `IsUuid` + +The `IsUuid` method determines if the given string is a UUID. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("550e8400-e29b-41d4-a716-446655440000").IsUuid() // true + +str.Of("krishan").IsUuid() // false +``` + +### `Kebab` + +The `Kebab` method converts the string to `kebab-case`. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("GoravelFramework").Kebab().String() // "goravel-framework" +``` + +### `LcFirst` + +The `LcFirst` method converts the first character of the string to lowercase. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel Framework").LcFirst().String() // "goravel Framework" +``` + +### `Length` + +The `Length` method returns the length of the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").Length() // 7 +``` + +### `Limit` + +The `Limit` method truncates the string to the given length. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("This is a beautiful morning").Limit(7).String() // "This is..." +``` + +Optionally, you may provide the second argument to change the string that is used to indicate the truncation. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("This is a beautiful morning").Limit(7, " (****)").String() // "This is (****)" +``` + +### `Lower` + +The `Lower` method converts the string to lowercase. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("GORAVEL").Lower().String() // "goravel" +``` + +### `LTrim` + +The `LTrim` method trims the left side of the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of(" Goravel ").LTrim().String() // "Goravel " + +str.Of("/framework/").LTrim("/").String() // "framework/" +``` + +### `Mask` + +The `Mask` method masks the string with the given mask character. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("krishan@email.com").Mask("*", 3).String() // "kri**************" +``` + +If needed, you may provide negative number to mask method which instruct the method to begin masking from the end of the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("krishan@email.com").Mask("*", -13, 3).String() // "kris***@email.com" + +str.Of("krishan@email.com").Mask("*", -13).String() // "kris**************" +``` + +### `Match` + +The `Match` method determines if the given string matches the given regular expression. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("This is a (test) string").Match(`\([^)]+\)`).String() // (test) +``` + +### `MatchAll` + +The `MatchAll` method determines if the given string matches all of the given regular expressions. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("abc123def456def").MatchAll(`\d+`) // []string{"123", "456"} +``` + +### `IsMatch` + +The `IsMatch` method determines if the given string matches (any of) the given regular expression. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello, Goravel!").IsMatch(`(?i)goravel`, `goravel!(.*)`) // true +``` + +### `NewLine` + +The `NewLine` method appends a newline character to the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").NewLine(2).Append("Framework").String() // "Goravel\n\nFramework" +``` + +### `PadBoth` + +The `PadBoth` method pads both sides of the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello").PadBoth(10, "_").String() // "__Hello___" +``` + +### `PadLeft` + +The `PadLeft` method pads the left side of the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello").PadLeft(10, "_").String() // "_____Hello" +``` + +### `PadRight` + +The `PadRight` method pads the right side of the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello").PadRight(10, "_").String() // "Hello_____" +``` + +### `Pipe` + +The `Pipe` method allows you to transform the string using a given closure. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").Pipe(func(s string) string { + return s + " Framework" +}).String() // "Goravel Framework" +``` + +### `Plural` + +The `Plural` method converts a singular string to its plural form. This function supports any of +the languages supported by the [pluralizer](pluralization.md). + +```go +import "github.com/goravel/framework/support/str" + +plural := str.Of("goose").Plural().String() +// "geese" +``` + +You may provide an integer argument to the function to retrieve the singular or plural form of the string: + +```go +import "github.com/goravel/framework/support/str" + +plural := str.Of("goose").Plural(2).String() +// "geese" + +plural = str.Of("goose").Plural(1).String() +// "goose" +``` + +### `Prepend` + +The `Prepend` method prepends the given value to the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Framework").Prepend("Goravel ").String() // "Goravel Framework" +``` + +### `Remove` + +The `Remove` method removes the given value(s) from the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello World").Remove("World").String() // "Hello " + +str.Of("Hello World").Remove("World", "Hello").String() // " " +``` + +### `Repeat` + +The `Repeat` method repeats the string a given number of times. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("a").Repeat(2).String() // "aa" +``` + +### `Replace` + +The `Replace` method replaces the given value in the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello World").Replace("World", "Krishan").String() // "Hello Krishan" +``` + +By default, the `Replace` method is case-sensitive. If you would like the method to be case-insensitive, you may pass `false` as the third argument. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello World").Replace("world", "Krishan", false).String() // "Hello Krishan" +``` + +### `ReplaceEnd` + +The `ReplaceEnd` method replaces the last occurrence of the given value in the string only if it is at the end of the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello World").ReplaceEnd("World", "Goravel").String() // "Hello Goravel" + +str.Of("Hello World").ReplaceEnd("Hello", "Goravel").String() // "Hello World" +``` + +### `ReplaceFirst` + +The `ReplaceFirst` method replaces the first occurrence of the given value in the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello World").ReplaceFirst("World", "Goravel").String() // "Hello Goravel" +``` + +### `ReplaceLast` + +The `ReplaceLast` method replaces the last occurrence of the given value in the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello World").ReplaceLast("World", "Goravel").String() // "Hello Goravel" +``` + +### `ReplaceMatches` + +The `ReplaceMatches` method replaces the given regular expression matches in the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello, Goravel!").ReplaceMatches(`goravel!(.*)`, "Krishan") // "Hello, Krishan!" +``` + +### `ReplaceStart` + +The `ReplaceStart` method replaces the first occurrence of the given value in the string only if it is at the start of the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello World").ReplaceStart("Hello", "Goravel").String() // "Goravel World" + +str.Of("Hello World").ReplaceStart("World", "Goravel").String() // "Hello World" +``` + +### `RTrim` + +The `RTrim` method trims the right side of the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of(" Goravel ").RTrim().String() // " Goravel" + +str.Of("/framework/").RTrim("/").String() // "/framework" +``` + +### `Singular` + +The `Singular` method converts a string to its singular form. This function supports any of +the languages supported by the [pluralizer](pluralization.md). + +```go +import "github.com/goravel/framework/support/str" + +singular := str.Of("heroes").Singular().String() +// "hero" +``` + +### `Snake` + +The `Snake` method converts the string to `snake_case`. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("GoravelFramework").Snake().String() // "goravel_framework" +``` + +### `Split` + +The `Split` method splits the string into an array of strings using the given delimiter. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello World").Split(" ") // []string{"Hello", "World"} +``` + +### `Squish` + +The `Squish` method replaces consecutive whitespace characters with a single space. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello World").Squish().String() // "Hello World" +``` + +### `Start` + +The `Start` method adds a single instance of the given value to the beginning of the string if it does not already start with the value. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("framework").Start("/").String() // "/framework" + +str.Of("/framework").Start("/").String() // "/framework" +``` + +### `StartsWith` + +The `StartsWith` method determines if the given string starts with (any) given value(s). The method is case-sensitive. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").StartsWith("Gor") // true + +str.Of("Hello World").StartsWith("Gor", "Hello") // true +``` + +### `String` + +The `String` method returns the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").String() // "Goravel" +``` + +### `Studly` + +The `Studly` method converts the string to `StudlyCase`. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("goravel_framework").Studly().String() // "GoravelFramework" +``` + +### `Substr` + +The `Substr` method returns the portion of the string starting at the given index and continuing for the given length. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").Substr(1, 3) // "ora" +``` + +### `Swap` + +The `Swap` method swaps multiple values in the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Golang is awesome").Swap(map[string]string{ + "Golang": "Go", + "awesome": "excellent", + }).String() // "Go is excellent" +``` + +### `Tap` + +The `Tap` method passes the string to the given closure and returns the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").Tap(func(s string) { + fmt.Println(s) +}).String() // "Goravel" +``` + +### `Test` + +The `Test` method determines if the given string matches the given regular expression. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello, Goravel!").Test(`goravel!(.*)`) // true +``` + +### `Title` + +The `Title` method converts the string to `Title Case`. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("goravel framework").Title().String() // "Goravel Framework" +``` + +### `Trim` + +The `Trim` method trims the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of(" Goravel ").Trim().String() // "Goravel" + +str.Of("/framework/").Trim("/").String() // "framework" +``` + +### `UcFirst` + +The `UcFirst` method converts the first character of the string to uppercase. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("goravel framework").UcFirst().String() // "Goravel framework" +``` + +### `UcSplit` + +The `UcSplit` method splits the string into an array of strings using uppercase characters. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("GoravelFramework").UcSplit() // []string{"Goravel", "Framework"} +``` + +### `Unless` + +The `Unless` method passes the string to the given closure and returns the string if the given condition is `false`. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").Unless(func(s *String) bool { + return false + }, func(s *String) *String { + return Of("Fallback Applied") + }).String() // "Fallback Applied" +``` + +### `Upper` + +The `Upper` method converts the string to uppercase. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("goravel").Upper().String() // "GORAVEL" +``` + +### `When` + +The `When` method passes the string to the given closure and returns the string if the given condition is `true`. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Bowen").When(true, func(s *str.String) *str.String { + return s.Append(" Han") +}).String() // "Bowen Han" +``` + +If necessary, you may provide the third argument to the `When` method which is a closure that will be executed when the condition is `false`. + +### `WhenContains` + +The `WhenContains` method passes the string to the given closure and returns the string if the given string contains the given value. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello Bowen").WhenContains("Hello", func(s *str.String) *str.String { + return s.Append(" Han") +}).String() // "Hello Bowen Han" +``` + +If necessary, you may provide the third argument to the `WhenContains` method which is a closure that will be executed when the string does not contain the given value. + +### `WhenContainsAll` + +The `WhenContainsAll` method passes the string to the given closure and returns the string if the given string contains all of the given values. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello Bowen").WhenContainsAll([]string{"Hello", "Bowen"}, func(s *str.String) *str.String { + return s.Append(" Han") +}).String() // "Hello Bowen Han" +``` + +If necessary, you may provide the third argument to the `WhenContainsAll` method which is a closure that will be executed when the string does not contain all the given values. + +### `WhenEmpty` + +The `WhenEmpty` method passes the string to the given closure and returns the string if the given string is empty. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("").WhenEmpty(func(s *str.String) *str.String { + return s.Append("Goravel") +}).String() // "Goravel" +``` + +### `WhenIsAscii` + +The `WhenIsAscii` method passes the string to the given closure and returns the string if the given string contains only ASCII characters. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").WhenIsAscii(func(s *str.String) *str.String { + return s.Append(" Framework") +}).String() // "Goravel Framework" + +str.Of("你好").WhenIsAscii(func(s *str.String) *str.String { + return s.Append(" Framework") +}).String() // "你好" +``` + +### `WhenNotEmpty` + +The `WhenNotEmpty` method passes the string to the given closure and returns the string if the given string is not empty. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").WhenNotEmpty(func(s *str.String) *str.String { + return s.Append(" Framework") +}).String() // "Goravel Framework" +``` + +### `WhenStartsWith` + +The `WhenStartsWith` method passes the string to the given closure and returns the string if the given string starts with the given value. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("hello world").WhenStartsWith("hello", func(s *str.String) *str.String { + return s.Title() +}).String() // "Hello World" +``` + +### `WhenEndsWith` + +The `WhenEndsWith` method passes the string to the given closure and returns the string if the given string ends with the given value. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("hello world").WhenEndsWith("world", func(s *str.String) *str.String { + return s.Title() +}).String() // "Hello World" +``` + +### `WhenExactly` + +The `WhenExactly` method passes the string to the given closure and returns the string if the given string is exactly equal to the given value. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").WhenExactly("Goravel", func(s *str.String) *str.String { + return s.Append(" Framework") +}).String() // "Goravel Framework" +``` + +### `WhenNotExactly` + +The `WhenNotExactly` method passes the string to the given closure and returns the string if the given string is not exactly equal to the given value. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Goravel").WhenNotExactly("Goravel", func(s *str.String) *str.String { + return s.Append(" Framework") +}).String() // "Goravel" +``` + +### `WhenIs` + +The `WhenIs` method passes the string to the given closure and returns the string if the given string matches the given pattern. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("foo/bar").WhenIs("foo/*", func(s *str.String) *str.String { + return s.Append("/baz") +}).String() // "foo/bar/baz" +``` + +### `WhenIsUlid` + +The `WhenIsUlid` method passes the string to the given closure and returns the string if the given string is a ULID. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("01E5Z6Z1Z6Z1Z6Z1Z6Z1Z6Z1Z6").WhenIsUlid(func(s *str.String) *str.String { + return s.Substr(0, 10) +}).String() // "01E5Z6Z1Z6" +``` + +### `WhenIsUuid` + +The `WhenIsUuid` method passes the string to the given closure and returns the string if the given string is a UUID. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("550e8400-e29b-41d4-a716-446655440000").WhenIsUuid(func(s *str.String) *str.String { + return s.Substr(0, 8) +}).String() // "550e8400" +``` + +### `WhenTest` + +The `WhenTest` method passes the string to the given closure and returns the string if the given string matches the given regular expression. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("goravel framework").WhenTest(`goravel(.*)`, func(s *str.String) *str.String { + return s.Append(" is awesome") +}).String() // "goravel framework is awesome" +``` + +### `WordCount` + +The `WordCount` method returns the number of words in the string. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello, World!").WordCount() // 2 +``` + +### `Words` + +The `Words` method limits the number of words in the string. If necessary, you may provide the second argument to change the string that is used to indicate the truncation. + +```go +import "github.com/goravel/framework/support/str" + +str.Of("Hello, World!").Words(1) // "Hello..." + +str.Of("Hello, World!").Words(1, " (****)") // "Hello (****)" +``` From 95923bfeed241de6b0013b1448ef311771f4aec1 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:22 +0800 Subject: [PATCH 022/163] New translations task-scheduling.md (Uzbek) [skip ci] Update translations (Uzbek) task-scheduling.md --- uz_UZ/digging-deeper/task-scheduling.md | 136 ++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 uz_UZ/digging-deeper/task-scheduling.md diff --git a/uz_UZ/digging-deeper/task-scheduling.md b/uz_UZ/digging-deeper/task-scheduling.md new file mode 100644 index 000000000..1a144fd63 --- /dev/null +++ b/uz_UZ/digging-deeper/task-scheduling.md @@ -0,0 +1,136 @@ +# Task Scheduling + +[[toc]] + +## Introduction + +In the past, you might need to create a cron configuration entry for each task that needed scheduling on your server. However, this approach can quickly become a pain as your task schedule is not in source control, and you have to SSH into your server to view or add/edit cron entries. + +Goravel's command scheduler offers a fresh approach to managing scheduled tasks on your server. With the scheduler, you can easily and clearly define your command schedule within your Goravel application. Using the scheduler, you only need to create a single cron entry on your server. + +## Defining Schedules + +To schedule tasks for your application, you can define them in the `WithSchedule` function in the `bootstrap/app.go` file. Let's consider an example to understand this better. In this case, we want to schedule a closure that will run every day at midnight. Inside this closure, we will execute a database query to clear a table: + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithSchedule(func() []schedule.Event { + return []schedule.Event{ + facades.Schedule().Call(func() { + facades.Orm().Query().Where("1 = 1").Delete(&models.User{}) + }).Daily(), + } + }). + WithConfig(config.Boot). + Start() +} +``` + +### Scheduling Artisan Commands + +In addition to scheduling closures, you can also schedule [Artisan commands](./artisan-console.md). For example, you may use the `Command` method to schedule an Artisan command using either the command's name or class. + +```go +facades.Schedule().Command("send:emails name").Daily(), +``` + +### Logging Level + +When `app.debug` is `true`, the console will print all logs. Otherwise, only `error` level logs will be printed. + +### Schedule Frequency Options + +We've already seen a few examples of how you may configure a task to run at specified intervals. However, there are many more task schedule frequencies avaibable to assign to tasks: + +| 方法 | 描述 | +| ------------------------ | --------------------------------------------------- | +| `.Cron("* * * * *")` | Custom Crone schedule (minutes) | +| `.Cron("* * * * * *")` | Custom Crone schedule (seconds) | +| `.EverySecond()` | Run the task every second | +| `.EveryTwoSeconds()` | Run the task every two seconds | +| `.EveryFiveSeconds()` | Run the task every five seconds | +| `.EveryTenSeconds()` | Run the task every ten seconds | +| `.EveryFifteenSeconds()` | Run the task every fifteen seconds | +| `.EveryTwentySeconds()` | Run the task every twenty seconds | +| `.EveryThirtySeconds()` | Run the task every thirty seconds | +| `.EveryMinute()` | Run the task every minute | +| `.EveryTwoMinutes()` | Run the task every two minutes | +| `.EveryThreeMinutes()` | Run the task every three minutes | +| `.EveryFourMinutes()` | Run the task every four minutes | +| `.EveryFiveMinutes()` | Run the task every five minutes | +| `.EveryTenMinutes()` | Run the task every ten minutes | +| `.EveryFifteenMinutes()` | Run the task every fifteen minutes | +| `.EveryThirtyMinutes()` | Run the task every thirty minutes | +| `.Hourly()` | Run the task every hour | +| `.HourlyAt(17)` | Run the task every hour at 17 minutes past the hour | +| `.EveryTwoHours()` | Run the task every two hours | +| `.EveryThreeHours()` | Run the task every three hours | +| `.EveryFourHours()` | Run the task every four hours | +| `.EverySixHours()` | Run the task every six hours | +| `.Daily()` | Run the task every day at midnight | +| `.DailyAt("13:00")` | Run the task every day at 13:00 | +| `.Days(1, 3, 5)` | Run the task every Monday, Wednesday, and Friday | +| `.Weekdays()` | Run the task every Monday to Friday | +| `.Weekends()` | Run the task every Saturday and Sunday | +| `.Mondays()` | Run the task every Monday | +| `.Tuesdays()` | Run the task every Tuesday | +| `.Wednesdays()` | Run the task every Wednesday | +| `.Thursdays()` | Run the task every Thursday | +| `.Fridays()` | Run the task every Friday | +| `.Saturdays()` | Run the task every Saturday | +| `.Sundays()` | Run the task every Sunday | +| `.Weekly()` | Run the task every week | +| `.Monthly()` | Run the task every month | +| `.Quarterly()` | Run the task every quarter | +| `.Yearly()` | Run the task every year | + +### Preventing Task Overlaps + +By default, scheduled tasks will continue to run even if a previous instance is still running. To prevent this, use the following methods: + +| 方法 | 描述 | +| ------------------------ | ---------------------- | +| `.SkipIfStillRunning()` | Skip if still running | +| `.DelayIfStillRunning()` | Delay if still running | + +```go +facades.Schedule().Command("send:emails name").EveryMinute().SkipIfStillRunning() +facades.Schedule().Command("send:emails name").EveryMinute().DelayIfStillRunning() +``` + +### Running Tasks On One Server + +> To utilize this feature, your application must be using the memcached, dynamodb, or redis cache driver as the default cache driver. In addition, all servers must be communicating with the same central cache server. + +If your application's scheduler runs on multiple servers, you can ensure that a scheduled job is executed on only one of them. For example, let's say you have a scheduled task that generates a new report every Friday night. If the task scheduler runs on three worker servers, the scheduled task will run on all three servers and create the report three times. This is not ideal! + +To prevent this, use the `OnOneServer` method when defining the scheduled task, which will make sure that the task runs on only one server. The first server to receive the task will secure an atomic lock on the job, preventing other servers from executing the same task at the same time: + +```go +facades.Schedule().Command("report:generate").Daily().OnOneServer() +``` + +Scheduled closures must be assigned a name if they are intended to be run on one server: + +```go +facades.Schedule().Call(func() { + fmt.Println("goravel") +}).Daily().OnOneServer().Name("goravel") +``` + +## Running The Scheduler + +The scheduler will be run automatically when calling `Start()` in the `main.go` file. You can also run tasks manually : + +```shell +./artisan schedule:run +``` + +## View All Tasks + +You can use the `schedule:list` command to view all tasks: + +```shell +./artisan schedule:list +``` From da3c8bfb1d82e1f5834609f7bc3b97be10ec305d Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:23 +0800 Subject: [PATCH 023/163] New translations compile.md (Uzbek) [skip ci] Update translations (Uzbek) compile.md --- uz_UZ/getting-started/compile.md | 141 +++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 uz_UZ/getting-started/compile.md diff --git a/uz_UZ/getting-started/compile.md b/uz_UZ/getting-started/compile.md new file mode 100644 index 000000000..046268496 --- /dev/null +++ b/uz_UZ/getting-started/compile.md @@ -0,0 +1,141 @@ +# Compile + +[[toc]] + +## Compile command + +The Goravel project can be compiled with the following command: + +```shell +# Select the system to compile +./artisan build + +# Specify the system to compile +./artisan build --os=linux +./artisan build -o=linux + +# Static compilation +./artisan build --static +./artisan build -s + +# Specify the output file name +./artisan build --name=goravel +./artisan build -n=goravel +``` + +## Manual compilation + +### Regular compilation + +```shell +go build . +``` + +#### Deploy Server + +The Following files and folders need to be uploaded to the server during deployment: + +``` +.env +./main // Compile the resulting binary file +./public // if exists +./resources // if exists +``` + +### Static compilation + +The package by regular compilation also needs to rely on the support of the deployment environment, the statically compiled files can be freely put to run on the specified platform without environment configuration. + +```shell +go build --ldflags "-extldflags -static" -o main . +``` + +### Cross compile + +Compilation is differentiated by platform, you need to select a matching compilation method according to the deployment situation. + +```shell +// Compile Linux environment +CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build . + +// Compile Windows environment +CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build . + +// Compile Mac environment +CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build . +``` + +## Docker + +Goravel has a default `Dockerfile` and `docker-compose.yml` file, you can use it directly, note that `APP_HOST` should be `0.0.0.0` at this time. + +```shell +docker build . +``` + +If you encounter slow download dependencies and time zone issues, you can optimize the Dockerfile content like the following script: + +```dockerfile +# China Special + +FROM golang:alpine AS builder +ENV GO111MODULE=on \ + CGO_ENABLED=0 \ + GOARCH="amd64" \ + GOOS=linux \ + GOPROXY=https://goproxy.cn,direct +WORKDIR /build +COPY . . +RUN go mod tidy +RUN go build --ldflags "-extldflags -static" -o main . +FROM alpine:latest +RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories +RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ + && echo "Asia/Shanghai" > /etc/timezone +WORKDIR /www +COPY --from=builder /build/.env /www/.env +COPY --from=builder /build/main /www/ + +# If exists +COPY --from=builder /build/database/ /www/database/ +COPY --from=builder /build/public/ /www/public/ +COPY --from=builder /build/storage/ /www/storage/ +COPY --from=builder /build/resources/ /www/resources/ + +ENTRYPOINT ["/www/main"] +``` + +### Docker Compose + +You can also quickly start the service with the following command: + +```shell +docker-compose build +docker-compose up +``` + +> Note: If you need external access, you need to change APP_HOST to 0.0.0.0 + +## Set timezone + +When the `app.timezone` configuration is not `UTC`, you need to set the timezone to the application during compilation. You can choose any of the following three methods: + +1. Add timezone settings in Dockerfile + +``` +RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone +``` + +2. Set timezone during compilation + +``` +go build -tags timetzdata . +``` + +3. Import timezone in `main.go` + +```shell +import ( + _ "time/tzdata" +) +``` From 4c07b74afbd481c49e08414e21e84b7d2208bb2d Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:24 +0800 Subject: [PATCH 024/163] New translations configuration.md (Uzbek) [skip ci] Update translations (Uzbek) configuration.md --- uz_UZ/getting-started/configuration.md | 72 ++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 uz_UZ/getting-started/configuration.md diff --git a/uz_UZ/getting-started/configuration.md b/uz_UZ/getting-started/configuration.md new file mode 100644 index 000000000..73f65008e --- /dev/null +++ b/uz_UZ/getting-started/configuration.md @@ -0,0 +1,72 @@ +# Configuration + +[[toc]] + +## Introduction + +All configuration files of the Goravel framework are stored in the `config` directory. You can view specific instructions and configure them flexibly according to project needs. + +## Environment Configuration + +Running applications in different environments usually requires different configurations. For example, you may want to turn on the Debug mode locally but don't need it in the production environment. + +Therefore, the framework provides the `.env.example` file in the root directory. You need to copy this file, rename it to `.env` before you start development, and modify the configuration items in the `.env` file according to your project needs. + +Note that the `.env` file should not be added to version control, because when multiple people collaborate, different developers may use different configurations, and different deployment environment configurations are different. + +In addition, if an intruder gains access to your code repository, there will be a risk of exposing sensitive configuration. If you want to add a new configuration item, you can add it to the `.env.example` file to synchronize the configuration of all developers. + +### Register Configuration + +All configuration files will be registered via the `WithConfig` function in the `bootstrap/app.go` file. Given that it's a `init` function in the config file, you don't need to register each configuration file one by one. Just call the `WithConfig` function as follows: + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithConfig(config.Boot). + Create() +} +``` + +## Retrieve Environment Configuration + +Use the following method to obtain the configuration items in the `.env` file: + +```go +// The first parameter is the configuration key, and the second parameter is the default value +facades.Config().Env("APP_NAME", "goravel") +``` + +## Access Configuration Values + +You can easily use the global `facades.Config()` function anywhere in the application to access the configuration values in the `config` directory. The access to the configuration value can use the "." syntax. You can also specify a default value, if the configuration option does not exist, the default value is returned: + +```go +// Get the configuration through assertion +facades.Config().Get("app.name", "goravel") + +// Get the configuration of the string type +facades.Config().GetString("app.name", "goravel") + +// Get the configuration of the int type +facades.Config().GetInt("app.int", 1) + +// Get the configuration of the bool type +facades.Config().GetBool("app.debug", true) +``` + +## Set Configuration + +```go +facades.Config().Add("path", "value1") +facades.Config().Add("path.with.dot.case1", "value1") +facades.Config().Add("path.with.dot", map[string]any{"case3": "value3"}) +``` + +## Get Project Information + +You can use the `artisan about` command to view the framework version, configuration, etc. + +```bash +./artisan about +``` From e6b9fae1ab1f63f2403d2217f1f8ade068104bd9 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:25 +0800 Subject: [PATCH 025/163] New translations contributions.md (Uzbek) [skip ci] Update translations (Uzbek) contributions.md --- uz_UZ/prologue/contributions.md | 153 ++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 uz_UZ/prologue/contributions.md diff --git a/uz_UZ/prologue/contributions.md b/uz_UZ/prologue/contributions.md new file mode 100644 index 000000000..badc9e98f --- /dev/null +++ b/uz_UZ/prologue/contributions.md @@ -0,0 +1,153 @@ +# Contribution Guide + +[[toc]] + +Goravel welcomes rich and diverse contributions from different talents, such as coding, translations, articles, tutorials, etc. After completing two features(5 `Good First Issue` == 1 `Feature`), you will be recognized as a core contributor. By completing one feature every three months, you can maintain this status. + +Let's make Goravel more efficient together! + +## Reward + +- Core developers will be eligible for benefits when Goravel benefits in the future. +- After completing a `Feature`, you will receive an official Goravel T-Shirt, with a maximum of 1 per major version release cycle. (PS: Because of the difference of country, you may need to help us to find a suitable supplier.) + +

+ +## Core Developers + +
+ + + +
+ +## Contributors + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +## Bug Feedback + +You can report Bug Feedback [here](https://github.com/goravel/goravel/issues/new?assignees=&labels=%E2%98%A2%EF%B8%8F+Bug%2Cbug&projects=&template=bug_report.yml&title=%F0%9F%90%9B+%5BBug%5D+), please search [Issue List](https://github.com/goravel/goravel/issues?q=is%3Aissue) for similar questions before submitting. The report should contain a title and a clear description of the problem, as much relevant information as possible, and a code sample that demonstrates the problem. The goal of Bug Feedback is to make it easy for yourself and other persons to reproduce the Bug and develop fixes. Goravel encourages committers to create a PR for the Bug repair at the same time, making the open-source project more actively developed. + +## Support Questions + +Goravel's GitHub issue trackers are not intended to provide Goravel help or support. Instead, use one of the following channels: + +- [GitHub Discussions](https://github.com/goravel/goravel/discussions) +- [Discord](https://github.com/goravel/goravel/tree/master#group) +- [WeChat](https://github.com/goravel/goravel/blob/master/README_zh.md#%E7%BE%A4%E7%BB%84) + +## Development Discussion + +You may propose new features or improvements to existing Goravel behavior in the Goravel framework repository's [GitHub discussion board](https://github.com/goravel/goravel/discussions). Informal discussion regarding bugs, new features, and implementation of existing features takes place in Discord or WeChat. Bowen, the maintainer of Goravel, is typically present in the group on weekdays from 9am-6pm (UTC+08:00), and sporadically present in the group at other times. + +## Add A New Language + +Welcome to add a new language to the Goravel documentation, you can submit an issue with the title `Add [Language] Language` and your [Crowdin](https://crowdin.com/) account to [goravel/goravel](https://github.com/goravel/goravel/issues/new). We will invite you to the Crowdin project. + +## Modify Existing Languages + +Given that the Goravel documentation supports i18n, only the English language can be modified by PR; other languages should be modified via [Crowdin](https://crowdin.com/). You can submit an issue with the title `Modify [Language] Language` and your [Crowdin](https://crowdin.com/) account to [goravel/goravel](https://github.com/goravel/goravel/issues/new). We will invite you to the Crowdin project. + +## Contribution + +### Find/Create Issue + +You can find or create an issue in [Issue List](https://github.com/goravel/goravel/issues), leave a message to express your willingness to deal with the issue, once confirmed by the repository maintainer, the process can be started. + +### Create PR + +- You can check out [this article](https://docs.github.com/en/get-started/quickstart/contributing-to-projects) if you are new to the process; +- During the development process, if you encounter a problem, you can describe the problem in detail in issue at any time for future communication, but before that, please make sure that you have tried to solve the problem through Google and other methods as much as possible; +- Before creating a PR, please improve the unit test coverage as much as possible to provide more stable functions; +- If you modify any file under the `contracts` folder, please run the `go tool mockery` command in the root directory to generate the mock file; +- When the PR is developed, please add the `Review Ready `, the maintainer will review it in a timely manner. +- After the PR is merged, the issue will be closed automatically if the description in the PR is set correctly; +- Goravel greatly appreciates your contribution and will add you to the home contribution list at the next release; ❤️ + +## Which Branch? + +**All** bug fixes should be sent to the latest version that supports bug fixes, unless they fix features that exist only in the upcoming release. + +**New features** or features with breaking changes should always be sent to the `master` branch. + +## Goravel Repository + +| Repository | Action | +| --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [goravel/goravel](https://github.com/goravel/goravel) | Goravel artisans | +| [goravel/goravel-lite](https://github.com/goravel/goravel-lite) | Goravel artisans of lite | +| [goravel/framework](https://github.com/goravel/framework) | Goravel main repository | +| [goravel/example](https://github.com/goravel/example) | Goravel example | +| [goravel/example-proto](https://github.com/goravel/example-proto) | The proto dependency of example | +| [goravel/example-package](https://github.com/goravel/example-package) | Example for package | +| [goravel/installer](https://github.com/goravel/installer) | A command-line tool that helps you to install the Goravel framework | +| [goravel/release](https://github.com/goravel/release) | Prover a simple way to release framework and packages version | +| [goravel/docs](https://github.com/goravel/docs) | Document | +| [goravel/s3](https://github.com/goravel/s3) | The S3 driver of Storage module | +| [goravel/oss](https://github.com/goravel/oss) | The OSS driver of Storage module | +| [goravel/cos](https://github.com/goravel/cos) | The COS driver of Storage module | +| [goravel/minio](https://github.com/goravel/minio) | The Minio driver of Storage module | +| [goravel/redis](https://github.com/goravel/redis) | The Redis driver of Cache module | +| [goravel/gin](https://github.com/goravel/gin) | The Gin driver of Route module | +| [goravel/fiber](https://github.com/goravel/fiber) | The Fiber driver of Route module | +| [goravel/postgres](https://github.com/goravel/postgres) | The Postgres driver of Database module | +| [goravel/mysql](https://github.com/goravel/mysql) | The MySQL driver of Database module | +| [goravel/sqlserver](https://github.com/goravel/sqlserver) | The SQLServer driver of Database module | +| [goravel/sqlite](https://github.com/goravel/sqlite) | The SQLite driver of Database module | +| [goravel/file-rotatelogs](https://github.com/goravel/file-rotatelogs) | Providers log splitting functionality for Log module | +| [goravel/.github](https://github.com/goravel/.github) | [Community health file](https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/creating-a-default-community-health-file) | + +## Code of Conduct + +The Goravel code of conduct is derived from the Laravel code of conduct. Any violations of the code of conduct may be reported to Bowen. + +- Participants will be tolerant of opposing views. +- Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks. +- When interpreting the words and actions of others, participants should always assume good intentions. +- Behavior that can be reasonably considered harassment will not be tolerated. + + From 6571556f3052324fc698f5a5946eca5f4af105cd Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:26 +0800 Subject: [PATCH 026/163] New translations directory-structure.md (Uzbek) [skip ci] Update translations (Uzbek) directory-structure.md --- uz_UZ/getting-started/directory-structure.md | 55 ++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 uz_UZ/getting-started/directory-structure.md diff --git a/uz_UZ/getting-started/directory-structure.md b/uz_UZ/getting-started/directory-structure.md new file mode 100644 index 000000000..4d9e480c3 --- /dev/null +++ b/uz_UZ/getting-started/directory-structure.md @@ -0,0 +1,55 @@ +# Directory Structure + +[[toc]] + +## Introduction + +The default file structure can make you better start project advancement, and you can also add new folders freely, but do not modify the default folders. + +## Folder Tree + +``` +goravel/ +├── app/ # Core application logic +│ ├── console/ # Artisan console commands +│ ├── grpc/ # gRPC controllers and middleware +│ ├── http/ # HTTP controllers and middleware +│ │ ├── controllers/ # HTTP request handlers +│ │ ├── middleware/ # HTTP middleware (auth, cors, etc.) +│ ├── models/ # ORM models +│ └── providers/ # Service providers +├── bootstrap/ # Application bootstrapping +│ └── app.go # Framework initialization +├── config/ # Application configuration files +├── database/ # Database related files +│ ├── migrations/ # Database migration files +│ ├── seeders/ # Database seeders +├── resources/ # Raw, uncompiled assets +│ └── views/ # View templates +├── routes/ # Application route definitions +├── storage/ # Application storage +├── tests/ # Automated tests +├── .air.toml # Air hot reload configuration +├── .env.example # Environment variables template +├── artisan # Artisan console entry script +├── go.mod # Go module dependencies +├── go.sum # Go module checksums +├── main.go # Application entry point +``` + +## Customize Directory Structure + +You can customize the directory structure by calling the `WithPath()` function in the `bootstrap/app.go` file. For example, if you want to change the default `app` directory to `src`, you can modify the `bootstrap/app.go` file as follows: + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithPaths(func(paths configuration.Paths) { + paths.App("src") + }). + WithConfig(config.Boot). + Create() +} +``` + +There are many other paths you can customize, such as `Config`, `Database`, `Routes`, `Storage`, and `Resources`. Just call the corresponding method on the `paths` object to set your desired directory. From a59ee423cea6c88263b7e087cda8e652ed0d24f9 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:27 +0800 Subject: [PATCH 027/163] New translations installation.md (Uzbek) [skip ci] Update translations (Uzbek) installation.md --- uz_UZ/getting-started/installation.md | 205 ++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 uz_UZ/getting-started/installation.md diff --git a/uz_UZ/getting-started/installation.md b/uz_UZ/getting-started/installation.md new file mode 100644 index 000000000..3eed28773 --- /dev/null +++ b/uz_UZ/getting-started/installation.md @@ -0,0 +1,205 @@ +# Installation + +[[toc]] + +## Server Requirements + +- Golang >= 1.23 + +## Installation + +### Using Goravel Installer + +Initialize the installer according to the [documentation](https://github.com/goravel/installer), and then initialize a new Goravel project using the following command: + +```shell +// Install the latest version of the goravel installer +go install github.com/goravel/installer/goravel@latest + +// Enter the directory where you want to install the project +goravel new blog +``` + +### Manual Installation + +#### goravel/goravel + +The complete framework with full features. + +```shell +// Download framework +git clone --depth=1 https://github.com/goravel/goravel.git && rm -rf goravel/.git* + +// Install dependencies +cd goravel && go mod tidy + +// Create .env environment configuration file +cp .env.example .env + +// Generate application key +./artisan key:generate +``` + +#### goravel/goravel-lite + +The lite framework with only essential features, suitable for building microservices or small applications. You can install additional facades as needed. + +```shell +// Download framework +git clone --depth=1 https://github.com/goravel/goravel-lite.git && rm -rf goravel-lite/.git* +s +// Install dependencies +cd goravel-lite && go mod tidy + +// Create .env environment configuration file +cp .env.example .env + +// Generate application key +./artisan key:generate + +// Install additional facades as needed, for example: +./artisan package:install Cache +``` + +> Please confirm your network if you encounter slow download dependencies. + +## Start Services + +### Start Services According To .env File In The Root Directory + +```shell +go run . +``` + +### Specify .env File To Start Services + +```shell +go run . --env=./.env +``` + +### Start Services Using Environment Variables + +```shell +APP_ENV=production APP_DEBUG=true go run . +``` + +### Live reload + +Install [air-verse/air](https://github.com/air-verse/air), Goravel has a built-in configuration file that can be used directly: + +``` +air +``` + +#### 🧰 After Installing Air + +Once you have successfully installed Air, you need to make sure it can be executed properly within your environment. +Depending on your setup, Air might not be automatically available as a command. +Here are two simple ways to ensure it runs correctly: + +--- + +#### 🪄 Option 1: Using a Helper Script (`air.sh`) + +If Air is installed but not recognized as a terminal command, you can create a small helper script that locates and runs it automatically. + +1. Create a new file in your project root: + +```bash +touch air.sh +chmod +x air.sh +``` + +2. Add the following content inside air.sh: + +```bash +#!/bin/bash +GO_PATH=$(go env GOPATH) +GO_BIN=$GO_PATH/bin/air + +if [ ! -f $GO_BIN ]; then + echo "❌ Air not found. Please install it first:" + echo " go install github.com/air-verse/air@latest" + exit 1 +fi + +echo "🚀 Starting Air..." +$GO_BIN +``` + +3. Run your project using: + +```bash +./air.sh +``` + +This ensures Air runs even if your `$PATH` does not include Go binaries. + +#### 💡 Option 2: Add Go Bin To PATH (Mac/Linux) + +If you prefer to run Air directly without a script, you can add Go bin directory to your PATH. + +For Zsh users: + +```bash +echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.zshrc +source ~/.zshrc +``` + +After this setup, you can start your project simply by running: + +```bash +air +``` + +#### ✅ Tip + +To verify that Air is installed and accessible, run: + +```bash +which air +``` + +If it doesn't return a valid path (for example `/Users/yourname/go/bin/air`), it means the helper script or the path hasn't been configured yet. + +## Configuration + +### Configuration files + +All configuration files of the Goravel framework are placed in the `config` directory. All configuration items have annotations, you can adjust them according to your needs. + +### Generate Application key + +You need to generate the application key after Goravel is installed locally. Running the command below, a 32-bit string will be generated on the `APP_KEY` key in the `.env` file. This key is mainly used for data encryption and decryption. + +```shell +./artisan key:generate +``` + +### Generate JWT Token + +You need to generate JWT Token if you use [Authentication](../security/authentication.md). + +```shell +./artisan jwt:secret +``` + +### Encrypt and decrypt env file + +You may want to add the production environment env file to version control, but you don't want to expose sensitive information, you can use the `env:encrypt` command to encrypt the env file: + +```shell +./artisan env:encrypt + +// Specify the file name and key +./artisan env:encrypt --name .env.safe --key BgcELROHL8sAV568T7Fiki7krjLHOkUc +``` + +Then use the `env:decrypt` command to decrypt the env file in the production environment: + +```shell +GORAVEL_ENV_ENCRYPTION_KEY=BgcELROHL8sAV568T7Fiki7krjLHOkUc ./artisan env:decrypt + +// or +./artisan env:decrypt --name .env.safe --key BgcELROHL8sAV568T7Fiki7krjLHOkUc +``` From 20eaebb3302e0650bf61886f4bdeb618fde3da03 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:28 +0800 Subject: [PATCH 028/163] New translations packages.md (Uzbek) [skip ci] Update translations (Uzbek) packages.md --- uz_UZ/getting-started/packages.md | 35 +++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 uz_UZ/getting-started/packages.md diff --git a/uz_UZ/getting-started/packages.md b/uz_UZ/getting-started/packages.md new file mode 100644 index 000000000..27f696463 --- /dev/null +++ b/uz_UZ/getting-started/packages.md @@ -0,0 +1,35 @@ +# Excellent Extend Packages + +You can find extended packages for Goravel here, and you can also create a PR for [goravel/docs](https://github.com/goravel/docs) to commit your owner package, please improve the test coverage of your package as much as possible. + +| Package | Description | Test Coverage\* | +| --------------------------------------------------------------------------------------- | ------------------------------------------- | --------------------- | +| [goravel/gin](https://github.com/goravel/gin) | The Gin driver for `facades.Route()` | 83.1% | +| [goravel/fiber](https://github.com/goravel/fiber) | The Fiber driver for `facades.Route()` | 81.0% | +| [goravel/cos](https://github.com/goravel/cos) | A COS disk driver for `facades.Storage()` | 80.2% | +| [goravel/minio](https://github.com/goravel/minio) | A Minio disk driver for `facades.Storage()` | 79.6% | +| [goravel/redis](https://github.com/goravel/redis) | A Redis disk driver for `facades.Cache()` | 79.1% | +| [goravel/s3](https://github.com/goravel/s3) | A S3 disk driver for `facades.Storage()` | 77.8% | +| [goravel/oss](https://github.com/goravel/oss) | A OSS disk driver for `facades.Storage()` | 76.5% | +| [goravel/installer](https://github.com/goravel/installer) | Goravel installer | 76.2% | +| [goravel/postgres](https://github.com/goravel/postgres) | A Postgres database driver | 73.7% | +| [goravel/mysql](https://github.com/goravel/mysql) | A MySQL database driver | 73.3% | +| [goravel/sqlserver](https://github.com/goravel/sqlserver) | A Sqlserver database driver | 60.6% | +| [goravel/sqlite](https://github.com/goravel/sqlite) | A Sqlite database driver | 45.2% | +| [portofolio-mager/goravel-mongodb](https://github.com/portofolio-mager/goravel-mongodb) | A MongoDB package | 16.9% | +| [hulutech-web/goravel-kit-cli](https://github.com/hulutech-web/goravel-kit-cli) | A goravel scaffold commandline tool | 15.2% | +| [hulutech-web/goravel-workflow](https://github.com/hulutech-web/goravel-workflow) | A workflow package | 4.4% | +| [hulutech-web/goravel-crud](https://github.com/hulutech-web/goravel-crud) | A goravel crud package | 4.2% | +| [hulutech-web/tinker](https://github.com/hulutech-web/tinker) | A goravel tinker package | 3.6% | +| [hulutech-web/goravel-socket](https://github.com/hulutech-web/goravel-socket) | A webSocket package | 0% | + +\***Note**: The packages are ordered based on their test rate. + +💡 Tip: To help more developers discover your work, you can also add relevant topics to your repository. +Recommended topic: [`goravel-package`](https://github.com/topics/goravel-package) + +- On GitHub, navigate to the main page of the repository. +- In the top right corner of the page, to the right of "About", click gear icon (settings). +- Under "Topics", start to type the topic you want to add to your repository to display a dropdown menu of any matching topics. +- Click the topic you want to add or continue typing to create a new topic. For example: `goravel-package`, `goravel` and any other relevant keywords. +- Click `Save changes` — this will make your package more discoverable. From 494cbea3a9afe99996e0bce16cea7cef74e53da3 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:28 +0800 Subject: [PATCH 029/163] New translations privacy.md (Uzbek) [skip ci] Update translations (Uzbek) privacy.md --- uz_UZ/prologue/privacy.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 uz_UZ/prologue/privacy.md diff --git a/uz_UZ/prologue/privacy.md b/uz_UZ/prologue/privacy.md new file mode 100644 index 000000000..1442d19aa --- /dev/null +++ b/uz_UZ/prologue/privacy.md @@ -0,0 +1,37 @@ +# Privacy Policy + +## Collection of Information + +We collect certain information about you when you visit goravel.dev. This information may include: + +- Information about the pages you visit on our website +- Any other information you provide voluntarily + +## Use of Information + +We may use the collected information for various purposes, including: + +- Personalizing your experience on our website +- Improving our website and services +- Contacting you regarding your inquiries or requests + +## Data Security + +We take the security of your data seriously. We implement appropriate technical and organizational measures to protect +your information from unauthorized access, disclosure, alteration, or destruction. + +## Third-Party Disclosure + +We may share your information with trusted third parties who assist us in operating our website or providing services to +you. These third parties are contractually obligated to keep your information confidential and secure. + +## Cookies + +Our website may use cookies to enhance your browsing experience. Cookies are small files stored on your device that +enable certain features and functionality. You may choose to disable cookies in your browser settings, but please note +that some parts of our website may not function properly. + +## Changes to this Policy + +We may update this Privacy Policy from time to time. Any changes will be posted on this page, and the revised policy +will take effect immediately upon posting. From bbf89ea0b39db4e0f53d017d5bd097a0f996694e Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:29 +0800 Subject: [PATCH 030/163] New translations index.md (Uzbek) [skip ci] Update translations (Uzbek) index.md --- uz_UZ/index.md | 202 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 uz_UZ/index.md diff --git a/uz_UZ/index.md b/uz_UZ/index.md new file mode 100644 index 000000000..676e88296 --- /dev/null +++ b/uz_UZ/index.md @@ -0,0 +1,202 @@ +--- +layout: home +title: Goravel - Full-featured Golang Development Framework + +head: + - [ + 'meta', + { + name: description, + content: Goravel is a Golang development framework with complete functions and excellent scalability. As a starting scaffolding to help Gopher quickly build their own applications. + } + ] + - [ + 'meta', + { property: og:url, content: https://www.goravel.dev } + ] + - [ 'meta', { property: og:type, content: website } ] + - [ + 'meta', + { + property: og:title, + content: Goravel - Full-featured Golang Development Framework + } + ] + - [ + 'meta', + { + property: og:description, + content: Goravel is a Golang development framework with complete functions and excellent scalability. As a starting scaffolding to help Gopher quickly build their own applications. + } + ] + - [ + 'meta', + { + property: og:image, + content: https://www.goravel.dev/meta.png + } + ] + - [ + 'meta', + { name: twitter:card, content: summary_large_image } + ] + - [ + 'meta', + { property: twitter:domain, content: www.goravel.dev } + ] + - [ + 'meta', + { property: twitter:url, content: https://www.goravel.dev } + ] + - [ + 'meta', + { + name: twitter:title, + content: Goravel - The Golang Framework For Web Artisans + } + ] + - [ + 'meta', + { + name: twitter:description, + content: Goravel is a Golang development framework with complete functions and excellent scalability. As a starting scaffolding to help Gopher quickly build their own applications. + } + ] + - [ + 'meta', + { + name: twitter:image, + content: https://www.goravel.dev/meta.png + } + ] + +hero: + name: Goravel + text: Full-featured Golang Development Framework + tagline: Componentization, High-performance, easy-to-extend, PHPers' first choice. + # image: /logo.svg + actions: + - theme: brand + text: Quick Start + link: /getting-started/installation + - theme: alt + text: 🌟 Github Star + link: https://github.com/goravel/goravel + target: _blank +features: + - title: 🧰 Lite Or Full-featured + details: You can choose between a lightweight version with essential features or a full-featured version that includes ORM, HTTP, logging, caching, and other basic tools for all development. + - title: 💻 Componentization + details: Modular design, each module is independent and can be used separately, making development and maintenance more convenient. + - title: 🚀 High-performance + details: Built with Golang, integrating multiple excellent extensions to create fast and responsive applications. + - title: 📈 Easy-to-extend + details: The module provides multiple drivers, and can develop extension packages according to needs, suitable for applications of any scale, from small projects to large systems. + - title: 👥 Active community + details: Supported by an active community, they contribute to its development, documentation, and continuous support. + - title: 🔄 PHPers' first choice + details: The framework style is consistent with Laravel, allowing PHPer to create powerful Golang applications without learning a new framework. Tribute to Laravel! +--- + +
Contributors
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
Group
+
+ +
+ +
Scan QR code to join the Wechat group
+
+ +
+ + + + +
Click me to join the Discord group
+
+ +
+
+ +
+
Reward
+
+ +
+ +
Scan QR code by Wechat
+
+ + +
+
+ + From 923345888c37b37c3742b5aaf8480974950b6f3c Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:30 +0800 Subject: [PATCH 031/163] New translations factories.md (Uzbek) [skip ci] Update translations (Uzbek) factories.md --- uz_UZ/orm/factories.md | 118 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 uz_UZ/orm/factories.md diff --git a/uz_UZ/orm/factories.md b/uz_UZ/orm/factories.md new file mode 100644 index 000000000..8a19700bc --- /dev/null +++ b/uz_UZ/orm/factories.md @@ -0,0 +1,118 @@ +# Factories + +[[toc]] + +## Introduction + +When testing your application or seeding your database, it might be necessary to insert a few records into your database beforehand. Instead of manually inputting values for each column, Goravel allows you to define a set of default attributes for each of your models by creating model factories. + +To see an example of how to write a factory, you can check out the `user_factory.go` file located in your application's `database/factories` directory. + +```go +package factories + +type UserFactory struct { +} + +// Definition Define the model's default state. +func (f *UserFactory) Definition() map[string]any { + return map[string]any{ + "Name": "Goravel", + } +} +``` + +As you can see, in their most basic form, factories are structs that have a `Definition` method. The method returns the default set of attribute values that should be used when creating a model with the factory. To generate a range of random data, you can rely on [brianvoe/gofakeit](https://github.com/brianvoe/gofakeit). + +## Generating Factories + +To create a factory, run the `make:factory` Artisan command: + +``` +go run . artisan make:factory PostFactory +``` + +The new factory `struct` will be placed in your `database/factories` directory. + +### Model & Factory Discovery Conventions + +After defining a factory, you can use the `Factory()` method in the model to bind the factory to the model: + +```go +package models + +import ( + "github.com/goravel/framework/contracts/database/factory" + "github.com/goravel/framework/database/orm" + + "goravel/database/factories" +) + +type User struct { + orm.Model + Name string + Avatar string + orm.SoftDeletes +} + +func (u *User) Factory() factory.Factory { + return &factories.UserFactory{} +} +``` + +## Creating Models Using Factories + +### Instantiating Models + +We can use the `Make` method to create models without persisting them in the database: + +```go +var user models.User +err := facades.Orm().Factory().Make(&user) +``` + +You may create a collection of many models using the `Count` method: + +```go +var users []models.User +err := facades.Orm().Factory().Count(2).Make(&users) +``` + +If you would like to override some of the default values of your models, you may pass `map[string]any` to the `Make` method. Only the specified attributes will be replaced while the rest of the attributes remain set to their default values as specified by the factory: + +```go +var user models.User +err := facades.Orm().Factory().Make(&user, map[string]any{ + "Avatar": "avatar", +}) +``` + +### Persisting Models + +The `Create` method creates and saves model instances to the database using Orm's `Save` method. + +```go +var user models.User +err := facades.Orm().Factory().Create(&user) + +var users []models.User +err := facades.Orm().Factory().Count(2).Create(&users) +``` + +You may override the factory's default model attributes by passing `map[string]any` of the attributes to the `Create` method: + +```go +var user models.User +err := facades.Orm().Factory().Create(&user, map[string]any{ + "Avatar": "avatar", +}) +``` + +### Ignore Model Event + +There may be [model event](../orm/getting-started.md#events) defined on the model, you can ignore those events with the `CreateQuietly` method: + +```go +var user models.User +err := facades.Orm().Factory().CreateQuietly(&user) +``` From 7a7487edb5011c71ea3733484848c1928a903041 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:32 +0800 Subject: [PATCH 032/163] New translations getting-started.md (Uzbek) [skip ci] Update translations (Uzbek) getting-started.md --- uz_UZ/orm/getting-started.md | 1120 ++++++++++++++++++++++++++++++++++ 1 file changed, 1120 insertions(+) create mode 100644 uz_UZ/orm/getting-started.md diff --git a/uz_UZ/orm/getting-started.md b/uz_UZ/orm/getting-started.md new file mode 100644 index 000000000..ff974a008 --- /dev/null +++ b/uz_UZ/orm/getting-started.md @@ -0,0 +1,1120 @@ +# Getting Started + +[[toc]] + +## Introduction + +Goravel provides a very simple and easy-to-use database interaction, developers can use `facades.Orm()` to operate. Please refer to [Configure Database](../database/getting-started) before starting. + +## Model Definition + +To create a custom model, refer to the model file `app/models/user.go` that is included in the framework. The `struct` in `app/models/user.go` contains two embedded frameworks: `orm.Model` and `orm.SoftDeletes`. These frameworks define `id`, `created_at`, `updated_at`, and `deleted_at` properties respectively. With `orm.SoftDeletes`, you can enable soft deletion for the model. + +### Model Convention + +1. The model is named with a big hump; +2. Use the plural form of the model "snake naming" as the table name; + +For example, the model name is `UserOrder`, and the table name is `user_orders`. + +### Create Model + +Use the `make:model` command to create a model: + +```shell +./artisan make:model User +./artisan make:model user/User +``` + +Created model file is located in `app/models/user.go` file, the content is as follows: + +```go +package models + +import ( + "github.com/goravel/framework/database/orm" +) + +type User struct { + orm.Model + Name string + Avatar string + orm.SoftDeletes +} +``` + +If you want to set the model field to `any`, you need to add an additional Tag: `gorm:"type:text"`: + +```go +type User struct { + orm.Model + Name string + Avatar string + Detail any `gorm:"type:text"` + orm.SoftDeletes +} +``` + +More Tag usage details can be found at: https://gorm.io/docs/models.html. + +#### Json Field + +If you want to use JSON field, you can define the field type as `datatypes.JSONMap` or a custom struct, and add the Tag: `gorm:"type:json"`: + +```go +package models + +import ( + "database/sql/driver" + "encoding/json" + "github.com/goravel/framework/database/orm" + "gorm.io/datatypes" +) + +type User struct { + orm.Model + Json1 datatypes.JSONMap `gorm:"type:json" json:"json1"` + Json2 *UserData `gorm:"type:json;serializer:json" json:"json2"` +} + +type UserData struct { + Name string `json:"name"` + Age int `json:"age"` +} + +func (r *UserData) Value() (driver.Value, error) { + return json.Marshal(r) +} + +func (r *UserData) Scan(value any) (err error) { + if data, ok := value.([]byte); ok && len(data) > 0 { + err = json.Unmarshal(data, &r) + } + return +} +``` + +#### Create Model based on data table + +```shell +./artisan make:model --table=users User + +// If the Model already exists, you can use the -f option to force overwrite +./artisan make:model --table=users -f User +``` + +If the data table has a field type that the framework cannot recognize, you can call the `facades.Schema().Extend()` method to extend the field type in the `bootstrap/app.go::WithCallback` function: + +```go +import "github.com/goravel/framework/contracts/schema" + +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithConfig(config.Boot). + WithCallback(func() { + facades.Schema().Extend(&schema.Extension{ + GoTypes: []schema.GoType{ + { + Pattern: "uuid", + Type: "uuid.UUID", + NullType: "uuid.NullUUID", + Imports: []string{"github.com/google/uuid"}, + }, + { + Pattern: "point", + Type: "geom.Point", + NullType: "*geom.Point", + Imports: []string{"github.com/twpayne/go-geom"}, + }, + }, + }) + }). + Create() +} +``` + +### Specify Table Name + +```go +package models + +import ( + "github.com/goravel/framework/database/orm" +) + +type User struct { + orm.Model + Name string + Avatar string + orm.SoftDeletes +} + +func (r *User) TableName() string { + return "goravel_user" +} +``` + +### Database Connections + +By default, all models utilize the default database connection configured for your application. If you wish to specify a distinct connection to be used when interacting with a particular model, you need to define a `Connection` method on the model. + +```go +package models + +import ( + "github.com/goravel/framework/database/orm" +) + +type User struct { + orm.Model + Name string + Avatar string + orm.SoftDeletes +} + +func (r *User) Connection() string { + return "postgres" +} +``` + +### Setting Global Scope + +Model supports setting the `GlobalScopes` method, which restricts the scope of the query, update, and delete operations: + +```go +import ( + contractsorm "github.com/goravel/framework/contracts/database/orm" + "github.com/goravel/framework/database/orm" +) + +type User struct { + orm.Model + Name string +} + +func (r *User) GlobalScopes() map[string]func(contractsorm.Query) contractsorm.Query { + return map[string]func(contractsorm.Query) contractsorm.Query{ + "name": func(query contractsorm.Query) contractsorm.Query { + return query.Where("name", "goravel") + }, + } +} +``` + +If you want to remove global scopes in a query, you can use the `WithoutGlobalScopes` function: + +```go +// Remove all global scopes +facades.Orm().Query().WithoutGlobalScopes().Get(&users) + +// Remove specified global scope +facades.Orm().Query().WithoutGlobalScopes("name").Get(&users) +``` + +## facades.Orm() available functions + +| Name | Action | +| ----------- | --------------------------------------------------------------------------------------- | +| Connection | [Specify Database Connection](#specify-database-connection) | +| DB | [Generic Database Interface sql.DB](#generic-database-interface-sql-db) | +| Query | [Get Database Instance](#get-database-instance) | +| Transaction | [Transaction](#transaction) | +| WithContext | [Inject Context](#inject-context) | + +## facades.Orm().Query() available functions + +| Functions | Action | +| --------------------------- | ----------------------------------------------------------------------------- | +| Avg | [Avg](#Avarage) | +| BeginTransaction | [Begin transaction](#transaction) | +| Commit | [Commit transaction](#transaction) | +| Count | [Count](#count) | +| Create | [Create](#create) | +| Cursor | [Cursor](#cursor) | +| Delete | [Delete](#delete) | +| Distinct | [Filter Repetition](#filter-repetition) | +| Driver | [Get Driver](#get-driver) | +| Exec | [Execute native update SQL](#execute-native-update-sql) | +| Exists | [Exists](#exists) | +| Find | [Query one or multiple lines by ID](#query-one-or-multiple-lines-by-id) | +| FindOrFail | [Not found return error](#not-found-return-error) | +| First | [Query one line](#query-one-line) | +| FirstOr | [Query or return data through callback](#query-one-line) | +| FirstOrCreate | [Retrieving Or Creating Models](#retrieving-or-creating-models) | +| FirstOrNew | [Retrieving Or New Models](#retrieving-or-creating-models) | +| FirstOrFail | [Not Found Error](#not-found-error) | +| ForceDelete | [Force delete](#delete) | +| Get | [Query multiple lines](#query-multiple-lines) | +| Group | [Group](#group-by--having) | +| Having | [Having](#group-by-having) | +| Join | [Join](#join) | +| Limit | [Limit](#limit) | +| LockForUpdate | [Pessimistic Locking](#pessimistic-locking) | +| Max | [Max](#Avarage) | +| Min | [Min](#Avarage) | +| Model | [Specify a model](#specify-table-query) | +| Offset | [Offset](#offset) | +| Order | [Order](#order) | +| OrderBy | [Order](#order) | +| OrderByDesc | [Order](#order) | +| InRandomOrder | [Order](#order) | +| OrWhere | [OrWhere](#where) | +| OrWhereNotIn | [OrWhereNotIn](#where) | +| OrWhereNull | [OrWhereNull](#where) | +| OrWhereIn | [OrWhereIn](#where) | +| OrWhereJsonContains | [OrWhereJsonContains](#where) | +| OrWhereJsonContainsKey | [OrWhereJsonContainsKey](#where) | +| OrWhereJsonDoesntContain | [OrWhereJsonDoesntContain](#where) | +| OrWhereJsonDoesntContainKey | [OrWhereJsonDoesntContainKey](#where) | +| OrWhereJsonLength | [OrWhereJsonLength](#where) | +| Paginate | [Paginate](#paginate) | +| Pluck | [Query single column](#query-single-column) | +| Raw | [Execute native SQL](#execute-native-sql) | +| Restore | [Restore](#restore) | +| Rollback | [Rollback transaction](#transaction) | +| Save | [Update a existing model](#update-a-existing-model) | +| SaveQuietly | [Saving a single model without events](#saving-a-single-model-without-events) | +| Scan | [Scan struct](#execute-native-sql) | +| Scopes | [Scopes](#scopes) | +| Select | [Specify Fields](#specify-fields) | +| SharedLock | [Pessimistic Locking](#pessimistic-locking) | +| Sum | [Sum](#Avarage) | +| Table | [Specify a table](#specify-table-query) | +| ToSql | [Get SQL](#get-sql) | +| ToRawSql | [Get SQL](#get-sql) | +| Update | [Update a single column](#update-a-single-column) | +| UpdateOrCreate | [Update or create](#update-or-create) | +| Where | [Where](#where) | +| WhereAll | [WhereAll](#where) | +| WhereAny | [WhereAny](#where) | +| WhereBetween | [WhereBetween](#where) | +| WhereNone | [WhereNone](#where) | +| WhereNotBetween | [WhereNotBetween](#where) | +| WhereNotIn | [WhereNotIn](#where) | +| WhereNull | [WhereNull](#where) | +| WhereIn | [WhereIn](#where) | +| WhereJsonContains | [WhereJsonContains](#where) | +| WhereJsonContainsKey | [WhereJsonContainsKey](#where) | +| WhereJsonDoesntContain | [WhereJsonDoesntContain](#where) | +| WhereJsonDoesntContainKey | [WhereJsonDoesntContainKey](#where) | +| WhereJsonLength | [WhereJsonLength](#where) | +| WithoutEvents | [Muting events](#muting-events) | +| WithTrashed | [Query soft delete data](#query-soft-delete-data) | + +## Query Builder + +### Inject Context + +```go +facades.Orm().WithContext(ctx) +``` + +### Specify Database Connection + +If multiple database connections are defined in `config/database.go`, you can use them through the `Connection` function of `facades.Orm()`. The connection name passed to `Connection` should be one of the connections configured in `config/database.go`: + +```go +facades.Orm().Connection("mysql") +``` + +### Generic Database Interface sql.DB + +Generic database interface sql.DB, then use the functionality it provides: + +```go +db, err := facades.Orm().DB() +db, err := facades.Orm().Connection("mysql").DB() + +// Ping +db.Ping() + +// Close +db.Close() + +// Returns database statistics +db.Stats() + +// SetMaxIdleConns sets the maximum number of connections in the idle connection pool +db.SetMaxIdleConns(10) + +// SetMaxOpenConns sets the maximum number of open connections to the database +db.SetMaxOpenConns(100) + +// SetConnMaxLifetime sets the maximum amount of time a connection may be reused +db.SetConnMaxLifetime(time.Hour) +``` + +### Get Database Instance + +Before each specific database operation, it's necessary to obtain an instance of the database. + +```go +facades.Orm().Query() +facades.Orm().Connection("mysql").Query() +facades.Orm().WithContext(ctx).Query() +``` + +### Select + +#### Query one line + +```go +var user models.User +facades.Orm().Query().First(&user) +// SELECT * FROM `users` ORDER BY `users`.`id` LIMIT 1; +``` + +Sometimes you may wish to perform some other action if no results are found. The `FirstOr` method will return a single model instance or, if no results are found, execute the given closure. You can set values to model in closure: + +```go +facades.Orm().Query().Where("name", "first_user").FirstOr(&user, func() error { + user.Name = "goravel" + + return nil +}) +``` + +#### Query one or multiple lines by ID + +```go +var user models.User +facades.Orm().Query().Find(&user, 1) +// SELECT * FROM `users` WHERE `users`.`id` = 1; + +var users []models.User +facades.Orm().Query().Find(&users, []int{1,2,3}) +// SELECT * FROM `users` WHERE `users`.`id` IN (1,2,3); +``` + +#### Not found return error + +```go +var user models.User +err := facades.Orm().Query().FindOrFail(&user, 1) +``` + +#### When the primary key of the user table is `string` type, you need to specify the primary key when calling `Find` method + +```go +var user models.User +facades.Orm().Query().Find(&user, "uuid=?" ,"a") +// SELECT * FROM `users` WHERE `users`.`uuid` = "a"; +``` + +#### Query multiple lines + +```go +var users []models.User +facades.Orm().Query().Where("id in ?", []int{1,2,3}).Get(&users) +// SELECT * FROM `users` WHERE id in (1,2,3); +``` + +#### Retrieving Or Creating Models + +The `FirstOrCreate` method searches for a database record using the specified column/value pairs. If the model cannot be found in the database, it creates a new record with the attributes from merging the first argument with the optional second argument. + +Similarly, the `FirstOrNew` method also tries to locate a record in the database based on the attributes given. However, if it is not found, a new instance of the model is returned. It's important to note that this new model has not been saved to the database yet and you need to manually call the `Save` method to do so. + +```go +var user models.User +facades.Orm().Query().Where("gender", 1).FirstOrCreate(&user, models.User{Name: "tom"}) +// SELECT * FROM `users` WHERE `gender` = 1 AND `users`.`name` = 'tom' ORDER BY `users`.`id` LIMIT 1; +// INSERT INTO `users` (`created_at`,`updated_at`,`name`) VALUES ('2023-09-18 12:51:32.556','2023-09-18 12:51:32.556','tom'); + +facades.Orm().Query().Where("gender", 1).FirstOrCreate(&user, models.User{Name: "tom"}, models.User{Avatar: "avatar"}) +// SELECT * FROM `users` WHERE `gender` = 1 AND `users`.`name` = 'tom' ORDER BY `users`.`id` LIMIT 1; +// INSERT INTO `users` (`created_at`,`updated_at`,`name`,`avatar`) VALUES ('2023-09-18 12:52:59.913','2023-09-18 12:52:59.913','tom','avatar'); + +var user models.User +facades.Orm().Query().Where("gender", 1).FirstOrNew(&user, models.User{Name: "tom"}) +// SELECT * FROM `users` WHERE `gender` = 1 AND `users`.`name` = 'tom' ORDER BY `users`.`id` LIMIT 1; + +facades.Orm().Query().Where("gender", 1).FirstOrNew(&user, models.User{Name: "tom"}, models.User{Avatar: "avatar"}) +// SELECT * FROM `users` WHERE `gender` = 1 AND `users`.`name` = 'tom' ORDER BY `users`.`id` LIMIT 1; +``` + +#### Not Found Error + +When the requested item is not found, the `First` method does not generate an error. To generate an error, use the `FirstOrFail` method: + +```go +var user models.User +err := facades.Orm().Query().FirstOrFail(&user) + +// import "github.com/goravel/framework/errors" +// if errors.Is(err, errors.OrmRecordNotFound) {} +``` + +### Where + +```go +facades.Orm().Query().Where("name", "tom") +facades.Orm().Query().Where("name = 'tom'") +facades.Orm().Query().Where("name = ?", "tom") +facades.Orm().Query().Where("name", "tom").Where(func(query orm.Query) orm.Query { + return query.Where("height", 180).Where("age", 18) +}) + +facades.Orm().Query().WhereBetween("age", 1, 10) +facades.Orm().Query().WhereNotBetween("age", 1, 10) +facades.Orm().Query().WhereNotIn("name", []any{"a"}) +facades.Orm().Query().WhereNull("name") +facades.Orm().Query().WhereIn("name", []any{"a"}) + +facades.Orm().Query().OrWhere("name", "tom") +facades.Orm().Query().OrWhereNotIn("name", []any{"a"}) +facades.Orm().Query().OrWhereNull("name") +facades.Orm().Query().OrWhereIn("name", []any{"a"}) + +var products []Product +facades.DB().Table("products").WhereAll([]string{"weight", "height"}, "=", 200).Find(&products) +// SQL: SELECT * FROM products WHERE weight = ? AND height = ? + +var users []User +facades.DB().Table("users").WhereAny([]string{"name", "email"}, "=", "John").Find(&users) +// SQL: SELECT * FROM users WHERE (name = ? OR email = ?) + +var products []Product +facades.DB().Table("products").WhereNone([]string{"age", "score"}, ">", 18).Find(&products) +// SQL: SELECT * FROM products WHERE NOT (age > ?) AND NOT (score > ?) +``` + +Query JSON columns + +```go +facades.Orm().Query().Where("preferences->dining->meal", "salad").First(&user) +facades.Orm().Query().Where("options->languages[0]", "en").First(&user) +facades.Orm().Query().WhereJsonContainsKey("contacts->personal->email").First(&user) +facades.Orm().Query().WhereJsonDoesntContainKey("contacts->personal->email").First(&user) +facades.Orm().Query().WhereJsonContains("options->languages", "en").First(&user) +facades.Orm().Query().WhereJsonContains("options->languages", []string{"en", "de"}).First(&user) +facades.Orm().Query().WhereJsonDoesntContain("options->languages", "en").First(&user) +facades.Orm().Query().WhereJsonDoesntContain("options->languages", []string{"en", "de"}).First(&user) +facades.Orm().Query().WhereJsonLength('options->languages', 1).First(&user) +facades.Orm().Query().WhereJsonLength('options->languages > ?', 1).First(&user) + +facades.Orm().Query().OrWhere("preferences->dining->meal", "salad").First(&user) +facades.Orm().Query().OrWhere("options->languages[0]", "en").First(&user) +facades.Orm().Query().OrWhereJsonContainsKey("contacts->personal->email").First(&user) +facades.Orm().Query().OrWhereJsonDoesntContainKey("contacts->personal->email").First(&user) +facades.Orm().Query().OrWhereJsonContains("options->languages", "en").First(&user) +facades.Orm().Query().OrWhereJsonContains("options->languages", []string{"en", "de"}).First(&user) +facades.Orm().Query().OrWhereJsonDoesntContain("options->languages", "en").First(&user) +facades.Orm().Query().OrWhereJsonDoesntContain("options->languages", []string{"en", "de"}).First(&user) +facades.Orm().Query().OrWhereJsonLength('options->languages', 1).First(&user) +facades.Orm().Query().OrWhereJsonLength('options->languages > ?', 1).First(&user) +``` + +### Limit + +```go +var users []models.User +facades.Orm().Query().Where("name", "tom").Limit(3).Get(&users) +// SELECT * FROM `users` WHERE name = 'tom' LIMIT 3; +``` + +### Offset + +```go +var users []models.User +facades.Orm().Query().Where("name", "tom").Offset(5).Limit(3).Get(&users) +// SELECT * FROM `users` WHERE name = 'tom' LIMIT 3 OFFSET 5; +``` + +### Order + +```go +var users []models.User +facades.Orm().Query().Where("name", "tom").Order("sort asc").Order("id desc").Get(&users) +// SELECT * FROM `users` WHERE name = 'tom' ORDER BY sort asc,id desc; + +facades.Orm().Query().Where("name", "tom").OrderBy("sort").Get(&users) +// SELECT * FROM `users` WHERE name = 'tom' ORDER BY sort asc; + +facades.Orm().Query().Where("name", "tom").OrderByDesc("sort").Get(&users) +// SELECT * FROM `users` WHERE name = 'tom' ORDER BY sort desc; + +facades.Orm().Query().Where("name", "tom").InRandomOrder().Get(&users) +// SELECT * FROM `users` WHERE name = 'tom' ORDER BY RAND(); +``` + +### Paginate + +```go +var users []models.User +var total int64 +facades.Orm().Query().Paginate(1, 10, &users, &total) +// SELECT count(*) FROM `users`; +// SELECT * FROM `users` LIMIT 10; +``` + +### Query Single Column + +```go +var ages []int64 +facades.Orm().Query().Model(&models.User{}).Pluck("age", &ages) +// SELECT `age` FROM `users`; +``` + +### Specify Table Query + +If you want to query some aggregate data, you need to specify a specific table. + +Specify a model + +```go +count, err := facades.Orm().Query().Model(&models.User{}).Count() +// SELECT count(*) FROM `users` WHERE deleted_at IS NULL; +``` + +Specify a table + +```go +count, err := facades.Orm().Query().Table("users").Count() +// SELECT count(*) FROM `users`; // get all records, whether deleted or not +``` + +### Get SQL + +Get SQL with placeholder: + +```go +facades.Orm().Query().ToSql().Get(models.User{}) +// SELECT * FROM "users" WHERE "id" = $1 AND "users"."deleted_at" IS NULL +``` + +Get SQL with value: + +```go +facades.Orm().Query().ToRawSql().Get(models.User{}) +// SELECT * FROM "users" WHERE "id" = 1 AND "users"."deleted_at" IS NULL +``` + +The methods can be called after `ToSql` and `ToRawSql`: `Count`, `Create`, `Delete`, `Find`, `First`, `Get`, `Pluck`, `Save`, `Sum`, `Update`. + +### Count + +```go +count, err := facades.Orm().Query().Table("users").Count() +// SELECT count(*) FROM `users` WHERE name = 'tom'; +``` + +### Specify Fields + +`Select` allows you to specify which fields to retrieve from the database, by default the ORM retrieves all fields. + +```go +facades.Orm().Query().Select("name", "age").Get(&users) +// SELECT `name`,`age` FROM `users`; +``` + +### Group By & Having + +```go +type Result struct { + Name string + Total int +} + +var result Result +facades.Orm().Query().Model(&models.User{}).Select("name", "sum(age) as total").Group("name").Having("name = ?", "tom").Get(&result) +// SELECT name, sum(age) as total FROM `users` GROUP BY `name` HAVING name = "tom"; +``` + +### Join + +```go +type Result struct { + Name string + Email string +} + +var result Result +facades.Orm().Query().Model(&models.User{}).Select("users.name", "emails.email").Join("left join emails on emails.user_id = users.id").Scan(&result) +// SELECT users.name, emails.email FROM `users` LEFT JOIN emails ON emails.user_id = users.id; +``` + +### Create + +```go +user := models.User{Name: "tom", Age: 18} +err := facades.Orm().Query().Create(&user) +// INSERT INTO users (name, age, created_at, updated_at) VALUES ("tom", 18, "2022-09-27 22:00:00", "2022-09-27 22:00:00"); + +// Not trigger model events +err := facades.Orm().Query().Table("users").Create(map[string]any{ + "name": "Goravel", +}) + +// Trigger model events +err := facades.Orm().Query().Model(&models.User{}).Create(map[string]any{ + "name": "Goravel", +}) +``` + +### Multiple create + +```go +users := []models.User{{Name: "tom", Age: 18}, {Name: "tim", Age: 19}} +err := facades.Orm().Query().Create(&users) + +err := facades.Orm().Query().Table("users").Create(&[]map[string]any{ + {"name": "Goravel"}, + {"name": "Framework"}, +}) + +err := facades.Orm().Query().Model(&models.User{}).Create(&[]map[string]any{ + {"name": "Goravel"}, + {"name": "Framework"}, +}) +``` + +> `created_at` and `updated_at` will be filled automatically. + +### Cursor + +Can be used to significantly reduce your application's memory consumption when iterating through tens of thousands of Eloquent model records. Note, the `Cursor` method can be used with `With` at the same time, please use [Lazy Eager Loading](./relationships.md#lazy-eager-loading) to load relationship in the `for` logic. + +```go +cursor, err := facades.Orm().Query().Model(models.User{}).Cursor() +if err != nil { + return err +} +for row := range cursor { + var user models.User + if err := row.Scan(&user); err != nil { + return err + } + fmt.Println(user) +} +``` + +### Save Model + +#### Update an existing model + +```go +var user models.User +facades.Orm().Query().First(&user) + +user.Name = "tom" +user.Age = 100 +facades.Orm().Query().Save(&user) +// UPDATE `users` SET `created_at`='2023-09-14 16:03:29.454',`updated_at`='2023-09-18 21:05:59.896',`name`='tom',`age`=100,`avatar`='' WHERE `id` = 1; +``` + +#### Update columns + +```go +facades.Orm().Query().Model(&models.User{}).Where("name", "tom").Update("name", "hello") +// UPDATE `users` SET `name`='hello',`updated_at`='2023-09-18 21:06:30.373' WHERE `name` = 'tom'; + +facades.Orm().Query().Model(&models.User{}).Where("name", "tom").Update(models.User{Name: "hello", Age: 18}) +facades.Orm().Query().Model(&models.User{}).Where("name", "tom").Update(map[string]any{"name": "hello", "age": 18}) +// UPDATE `users` SET `updated_at`='2023-09-18 21:07:06.489',`name`='hello',`age`=18 WHERE `name` = 'tom'; +``` + +> When updating with `struct`, Orm will only update non-zero fields. You might want to use `map` to update attributes or use `Select` to specify fields to update. Note that `struct` can only be `Model`, if you want to update with non `Model`, you need to use `.Table("users")`, however, the `updated_at` field cannot be updated automatically at this time. + +#### Update JSON fields + +```go +facades.Orm().Query().Model(&models.User{}).Where("id", 1).Update("options->enabled", true) +facades.Orm().Query().Model(&models.User{}).Where("id", 1).Update("options->languages[0]", "en") +facades.Orm().Query().Model(&models.User{}).Where("id", 1).Update("options->languages", []string{"en", "de"}) +facades.Orm().Query().Model(&models.User{}).Where("id", 1).Update(map[string]any{ + "preferences->dining->meal": "salad", + "options->languages[0]": "en", + "options->enabled": true, +}) +``` + +#### Update or create + +Query by `name`, if not exist, create by `name`, `avatar`, if exists, update `avatar` based on `name`: + +```go +facades.Orm().Query().UpdateOrCreate(&user, models.User{Name: "name"}, models.User{Avatar: "avatar"}) +// SELECT * FROM `users` WHERE `users`.`name` = 'name' AND `users`.`deleted_at` IS NULL ORDER BY `users`.`id` LIMIT 1; +// INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`avatar`) VALUES ('2023-03-11 10:11:08.869','2023-03-11 10:11:08.869',NULL,'name','avatar'); +// UPDATE `users` SET `name`='name',avatar`='avatar',`updated_at`='2023-03-11 10:11:08.881' WHERE users`.`deleted_at` IS NULL AND `id` = 1; +``` + +### Delete + +Delete by model, the number of rows affected by the statement is returned by the method: + +```go +var user models.User +facades.Orm().Query().Find(&user, 1) +res, err := facades.Orm().Query().Delete(&user) +res, err := facades.Orm().Query().Model(&models.User{}).Where("id", 1).Delete() +res, err := facades.Orm().Query().Table("users").Where("id", 1).Delete() +// DELETE FROM `users` WHERE `users`.`id` = 1; + +num := res.RowsAffected +``` + +Multiple delete + +```go +facades.Orm().Query().Where("name", "tom").Delete(&models.User{}) +// DELETE FROM `users` WHERE name = 'tom'; +``` + +Want to force delete a soft-delete data. + +```go +facades.Orm().Query().Where("name", "tom").ForceDelete(&models.User{}) +facades.Orm().Query().Model(&models.User{}).Where("name", "tom").ForceDelete() +facades.Orm().Query().Table("users").Where("name", "tom").ForceDelete() +``` + +You can delete records with model associations via `Select`: + +```go +// Delete Account of user when deleting user +facades.Orm().Query().Select("Account").Delete(&user) + +// Delete Orders and CreditCards of user when deleting user +facades.Orm().Query().Select("Orders", "CreditCards").Delete(&user) + +// Delete all child associations of user when deleting user +facades.Orm().Query().Select(orm.Associations).Delete(&user) + +// Delete all Account of users when deleting users +facades.Orm().Query().Select("Account").Delete(&users) +``` + +Note: The associations will be deleted only if the primary key of the record is not empty, and Orm uses these primary keys as conditions to delete associated records: + +```go +// Delete user that name='goravel', but don't delete account of user +facades.Orm().Query().Select("Account").Where("name", "goravel").Delete(&models.User{}) + +// Delete user that name='goravel' and id = 1, and delete account of user +facades.Orm().Query().Select("Account").Where("name", "goravel").Delete(&models.User{ID: 1}) + +// Delete user that id = 1 and delete account of that user +facades.Orm().Query().Select("Account").Delete(&models.User{ID: 1}) +``` + +If execute batch delete without any conditions, ORM doesn't do that and returns an error. So you have to add some conditions, or use native SQL. + +### Query Soft Delete Data + +```go +var user models.User +facades.Orm().Query().WithTrashed().First(&user) +``` + +### Filter Repetition + +```go +var users []models.User +facades.Orm().Query().Distinct("name").Find(&users) +``` + +### Get Driver + +```go +driver := facades.Orm().Query().Driver() + +// Judge driver +if driver == orm.DriverMysql {} +``` + +### Execute Native SQL + +```go +type Result struct { + ID int + Name string + Age int +} + +var result Result +facades.Orm().Query().Raw("SELECT id, name, age FROM users WHERE name = ?", "tom").Scan(&result) +``` + +### Execute Native Update SQL + +The number of rows affected by the statement is returned by the method: + +```go +res, err := facades.Orm().Query().Exec("DROP TABLE users") +// DROP TABLE `users`; + +num := res.RowsAffected +``` + +### Exists + +```go +exists, err := facades.Orm().Query().Model(&models.User{}).Where("name", "tom").Exists() +``` + +### Restore + +```go +facades.Orm().Query().WithTrashed().Restore(&models.User{ID: 1}) +facades.Orm().Query().Model(&models.User{ID: 1}).WithTrashed().Restore() +// UPDATE `users` SET `deleted_at`=NULL WHERE `id` = 1; +``` + +### Transaction + +You can execute a transaction by `Transaction` function. + +```go +import ( + "github.com/goravel/framework/contracts/database/orm" + + "goravel/app/facades" + "goravel/app/models" +) + +... + +return facades.Orm().Transaction(func(tx orm.Query) error { + var user models.User + + return tx.Find(&user, user.ID) +}) +``` + +You can also manually control the flow of the transaction yourself: + +```go +tx, err := facades.Orm().Query().BeginTransaction() +user := models.User{Name: "Goravel"} +if err := tx.Create(&user); err != nil { + err := tx.Rollback() +} else { + err := tx.Commit() +} +``` + +### Scopes + +Allows you to specify commonly used queries that can be referenced when method are called. + +```go +func Paginator(page string, limit string) func(methods orm.Query) orm.Query { + return func(query orm.Query) orm.Query { + page, _ := strconv.Atoi(page) + limit, _ := strconv.Atoi(limit) + offset := (page - 1) * limit + + return query.Offset(offset).Limit(limit) + } +} + +// scopes.Paginator is a custom function: func(ormcontract.Query) ormcontract.Query +facades.Orm().Query().Scopes(scopes.Paginator(page, limit)).Find(&entries) +``` + +### Raw Expressions + +You can use the `db.Raw` method to update fields: + +```go +import "github.com/goravel/framework/database/db" + +facades.Orm().Query().Model(&user).Update("age", db.Raw("age - ?", 1)) +// UPDATE `users` SET `age`=age - 1,`updated_at`='2023-09-14 14:03:20.899' WHERE `users`.`deleted_at` IS NULL AND `id` = 1; +``` + +### Pessimistic Locking + +The query builder also includes a few functions to help you achieve "pessimistic locking" when executing your `select` statements. + +To execute a statement with a "shared lock", you may call the `SharedLock` method. A shared lock prevents the selected rows from being modified until your transaction is committed: + +```go +var users []models.User +facades.Orm().Query().Where("votes > ?", 100).SharedLock().Get(&users) +``` + +Alternatively, you may use the `LockForUpdate` method. A "for update" lock prevents the selected records from being modified or from being selected with another shared lock: + +```go +var users []models.User +facades.Orm().Query().Where("votes > ?", 100).LockForUpdate().Get(&users) +``` + +### Avarage + +```go +var sum int +err := facades.Orm().Query().Model(models.User{}).Sum("id", &sum) + +var avg float64 +err := facades.Orm().Query().Model(models.User{}).Average("age", &avg) + +var max int +err := facades.Orm().Query().Model(models.User{}).Max("age", &max) + +var min int +err := facades.Orm().Query().Model(models.User{}).Min("age", &min) +``` + +## Events + +Orm models dispatch several events, allowing you to hook into the following moments in a model's lifecycle: `Retrieved`, `Creating`, `Created`, `Updating`, `Updated`, `Saving`, `Saved`, `Deleting`, `Deleted`, `ForceDeleting`, `ForceDeleted`, `Restored`, `Restoring`. + +The `Retrieved` event will dispatch when an existing model is retrieved from the database. When a new model is saved for the first time, the `Creating` and `Created` events will dispatch. The `Updating` / `Updated` events will dispatch when an existing model is modified and the `Save` method is called. The `Saving` / `Saved` events will dispatch when a model is created or updated - even if the model's attributes have not been changed. Event names ending with `-ing` are dispatched before any changes to the model are persisted, while events ending with `-ed` are dispatched after the changes to the model are persisted. + +Note: All events will only be triggered when operating a model. For example, if you want to trigger the `Updating` and `Updated` events when calling the `Update` method, you need to pass the existing model to the `Model` method: `facades.Orm().Query().Model(&user).Update("name", "Goravel")`. + +To start listening to model events, define a `DispatchesEvents` method on your model. This property maps various points of the model's lifecycle to your own event classes. + +```go +import ( + contractsorm "github.com/goravel/framework/contracts/database/orm" + "github.com/goravel/framework/database/orm" +) + +type User struct { + orm.Model + Name string +} + +func (u *User) DispatchesEvents() map[contractsorm.EventType]func(contractsorm.Event) error { + return map[contractsorm.EventType]func(contractsorm.Event) error{ + contractsorm.EventCreating: func(event contractsorm.Event) error { + return nil + }, + contractsorm.EventCreated: func(event contractsorm.Event) error { + return nil + }, + contractsorm.EventSaving: func(event contractsorm.Event) error { + return nil + }, + contractsorm.EventSaved: func(event contractsorm.Event) error { + return nil + }, + contractsorm.EventUpdating: func(event contractsorm.Event) error { + return nil + }, + contractsorm.EventUpdated: func(event contractsorm.Event) error { + return nil + }, + contractsorm.EventDeleting: func(event contractsorm.Event) error { + return nil + }, + contractsorm.EventDeleted: func(event contractsorm.Event) error { + return nil + }, + contractsorm.EventForceDeleting: func(event contractsorm.Event) error { + return nil + }, + contractsorm.EventForceDeleted: func(event contractsorm.Event) error { + return nil + }, + contractsorm.EventRetrieved: func(event contractsorm.Event) error { + return nil + }, + contractsorm.EventRestored: func(event contractsorm.Event) error { + return nil + }, + contractsorm.EventRestoring: func(event contractsorm.Event) error { + return nil + }, + } +} +``` + +> Note: Just register the events you need. Model events are not dispatched when doing batch operations through Orm. + +### Observers + +#### Defining Observers + +If you are listening to many events on a given model, you may use observers to group all of your listeners into a single class. Observer classes have method names that reflect the Eloquent events you wish to listen for. Each of these methods receives the affected model as their only argument. The `make:observer` Artisan command is the easiest way to create a new observer class: + +```shell +./artisan make:observer UserObserver +./artisan make:observer user/UserObserver +``` + +This command will place the new observer in your `app/observers` directory. If this directory does not exist, Artisan will create it for you. Your fresh observer will look like the following: + +```go +package observers + +import ( + "fmt" + + "github.com/goravel/framework/contracts/database/orm" +) + +type UserObserver struct{} + +func (u *UserObserver) Created(event orm.Event) error { + return nil +} + +func (u *UserObserver) Updated(event orm.Event) error { + return nil +} + +func (u *UserObserver) Deleted(event orm.Event) error { + return nil +} + +func (u *UserObserver) ForceDeleted(event orm.Event) error { + return nil +} +``` + +The template observer only contains some events, you can add other events according to your needs. + +To register an observer, you need to call the `Observe` method on the model you wish to observe. You can register observers in the `bootstrap/app.go::WithCallback` function: + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithConfig(config.Boot). + WithCallback(func() { + facades.Orm().Observe(models.User{}, &observers.UserObserver{}) + }). + Create() +} +``` + +> Note: If you set `DispatchesEvents` and `Observer` at the same time, only `DispatchesEvents` will be applied. + +#### Parameter in Observer + +The `event` parameter will be passed to all observers: + +| Method | Action | +| ------------ | ---------------------------------------------------------------------------------------------------------- | +| Context | Get context that passed by `facades.Orm().WithContext()` | +| GetAttribute | Get the modified value, if not modified, get the original value, if there is no original value, return nil | +| GetOriginal | Get the original value, if there is no original value, return nil | +| IsDirty | Determine whether the field is modified | +| IsClean | IsDirty reverse | +| Query | Get a new Query, which can be used with transaction | +| SetAttribute | Set a new value for a field | + +### Muting Events + +You may occasionally need to temporarily "mute" all events fired by a model. You may achieve this using the `WithoutEvents` method: + +```go +var user models.User +facades.Orm().Query().WithoutEvents().Find(&user, 1) +``` + +#### Saving A Single Model Without Events + +Sometimes you may wish to "save" a given model without dispatching any events. You may accomplish this with the `SaveQuietly` method: + +```go +var user models.User +err := facades.Orm().Query().FindOrFail(&user, 1) +user.Name = "Goravel" +err := facades.Orm().Query().SaveQuietly(&user) +``` From b9c6319301097ffedd06fbb0912941a953b6f4bf Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:33 +0800 Subject: [PATCH 033/163] New translations relationships.md (Uzbek) [skip ci] Update translations (Uzbek) relationships.md --- uz_UZ/orm/relationships.md | 532 +++++++++++++++++++++++++++++++++++++ 1 file changed, 532 insertions(+) create mode 100644 uz_UZ/orm/relationships.md diff --git a/uz_UZ/orm/relationships.md b/uz_UZ/orm/relationships.md new file mode 100644 index 000000000..7fc82f5c9 --- /dev/null +++ b/uz_UZ/orm/relationships.md @@ -0,0 +1,532 @@ +# Relationships + +[[toc]] + +## Introduction + +It's common for database tables to be interconnected. For instance, a blog post may have many comments, or an order may be linked to the user who placed it. `Orm` simplifies managing and dealing with such relationships, and it can handle various common relationships: + +- [One To One](#One-To-One) +- [One To Many](#One-To-Many) +- [Many To Many](#Many-To-Many) +- [Polymorphic](#Polymorphic) + +## Defining Relationships + +### One To One + +A one-to-one relationship is a very basic type of database relationship. For example, a `User` model might be associated with one `Phone` model. + +```go +type User struct { + orm.Model + Name string + Phone *Phone +} + +type Phone struct { + orm.Model + UserID uint + Name string +} +``` + +When using `Orm`, it automatically assigns the foreign key to the relationship based on the parent model name. For instance, the `Phone` model is assumed to have a `UserID` foreign key by default. However, if you wish to change this convention, you can add a `foreignKey` tag to the `Phone` field in `User` model. (This also applies to other relationships.) + +```go +type User struct { + orm.Model + Name string + Phone *Phone `gorm:"foreignKey:UserName"` +} + +type Phone struct { + orm.Model + UserName string + Name string +} +``` + +Additionally, when using `Orm`, it is assumed that the foreign key should match the primary key column of the parent. This means that `Orm` will search for the user's `ID` column value in the `UserId` column of the `Phone` record. If you wish to use a primary key value other than `ID`, you can add a "Tag" reference to the `Phone` field in `User` model. To do this, simply pass a third argument to the `hasOne` method. (Other relationship setups are similar.) + +```go +type User struct { + orm.Model + Name string + Phone *Phone `gorm:"foreignKey:UserName;references:name"` +} + +type Phone struct { + orm.Model + UserName string + Name string +} +``` + +#### Defining The Inverse Of The Relationship + +We can access the `Phone` model from our `User` model. Now, we need to establish a relationship on `Phone` model that allows us to access the phone's owner. To do this, we can define a `User` field in `Phone` model. + +```go +type User struct { + orm.Model + Name string +} + +type Phone struct { + orm.Model + UserID uint + Name string + User *User +} +``` + +### One To Many + +A one-to-many relationship is used to define relationships where a single model is the parent to one or more child models. For example, a blog post may have an infinite number of comments. Like all other `Orm` relationships, one-to-many relationships are defined by defining a field on your `Orm` model: + +```go +type Post struct { + orm.Model + Name string + Comments []*Comment +} + +type Comment struct { + orm.Model + PostID uint + Name string +} +``` + +Remember, `Orm` will automatically determine the proper foreign key column for the `Comment` model. By convention, Orm will take the "hump case" name of the parent model and suffix it with `ID`. So, in this example, Orm will assume the foreign key column on the `Comment` model is `PostID`. + +### One To Many (Inverse) / Belongs To + +Now that we can access all of a post's comments, let's define a relationship to allow a comment to access its parent post. To define the inverse of a `One To Many` relationship, define a relationship method on the child model which calls the `belongsTo` method: + +```go +type Post struct { + orm.Model + Name string + Comments []*Comment +} + +type Comment struct { + orm.Model + PostID uint + Name string + Post *Post +} +``` + +## Many To Many Relationships + +Many-to-many relations are slightly more complicated than `One To One` and `One To Many` relationships. An example of a many-to-many relationship is a user that has many roles and those roles are also shared by other users in the application. For example, a user may be assigned the role of "Author" and "Editor"; however, those roles may also be assigned to other users as well. So, a user has many roles and a role has many users. + +### Table Structure + +To define this relationship, three database tables are needed: `users`, `roles`, and `role_user`. The `role_user` table naming can be customized and it contains `user_id` and `role_id` columns. This table is used as an intermediate table linking users and roles. + +Remember, since a role can belong to many users, we cannot simply place a `user_id` column on the `roles` table. This would mean that a role could only belong to a single user. In order to provide support for roles being assigned to multiple users, the `role_user` table is needed. We can summarize the relationship's table structure like so: + +``` +users + id - integer + name - string + +roles + id - integer + name - string + +role_user + user_id - integer + role_id - integer +``` + +### Model Structure + +We can define a `Roles` field on `User` model: + +```go +type User struct { + orm.Model + Name string + Roles []*Role `gorm:"many2many:role_user"` +} + +type Role struct { + orm.Model + Name string +} +``` + +### Defining The Inverse Of The Relationship + +To define the inverse of the relationship, just define a `Users` field in `Role` model and append a Tag. + +```go +type User struct { + orm.Model + Name string + Roles []*Role `gorm:"many2many:role_user"` +} + +type Role struct { + orm.Model + Name string + Users []*User `gorm:"many2many:role_user"` +} +``` + +### Custom intermediate table + +In general, the intermediate table foreign key is named by the "snake case" of the parent model name, you can override them by `joinForeignKey`, `joinReferences`: + +```go +type User struct { + orm.Model + Name string + Roles []*Role `gorm:"many2many:role_user;joinForeignKey:UserName;joinReferences:RoleName"` +} + +type Role struct { + orm.Model + Name string +} +``` + +Table structure: + +``` +users + id - integer + name - string + +roles + id - integer + name - string + +role_user + user_name - integer + role_name - integer +``` + +## Polymorphic + +A polymorphic relationship allows the child model to belong to more than one type of model using a single association. For example, imagine you are building an application that allows users to share blog posts and videos. In such an application, a `Comment` model might belong to both the `Post` and `Video` models. + +### Table structure + +A polymorphic relation is similar to a normal relation; however, the child model can belong to more than one type of model using a single association. For example, a blog `Post` and a `User` may share a polymorphic relation to an `Image` model. Using a polymorphic relation allows you to have a single table of unique images that may be associated with posts and users. First, let's examine the table structure: + +``` +posts + id - integer + name - string + +videos + id - integer + name - string + +images + id - integer + url - string + imageable_id - integer + imageable_type - string + +comments + id - integer + body - text + commentable_id - integer + commentable_type - string +``` + +Note the `imageable_id` and `imageable_type` columns on the `images` table. The `imageable_id` column will contain the ID value of the post or user, while the `imageable_type` column will contain the class name of the parent model. The `imageable_type` column is used by Orm to determine which "type" of parent model to return when accessing the `imageable` relation. The `comments` table is similar. + +### Model Structure + +Next, let's examine the model definitions needed to build this relationship: + +```go +type Post struct { + orm.Model + Name string + Image *Image `gorm:"polymorphic:Imageable"` + Comments []*Comment `gorm:"polymorphic:Commentable"` +} + +type Video struct { + orm.Model + Name string + Image *Image `gorm:"polymorphic:Imageable"` + Comments []*Comment `gorm:"polymorphic:Commentable"` +} + +type Image struct { + orm.Model + Name string + ImageableID uint + ImageableType string +} + +type Comment struct { + orm.Model + Name string + CommentableID uint + CommentableType string +} +``` + +You can change the polymorphic value by `polymorphicValue` Tag, such as: + +```go +type Post struct { + orm.Model + Name string + Image *Image `gorm:"polymorphic:Imageable;polymorphicValue:master"` +} +``` + +## Querying Associations + +For example, imagine a blog application in which a `User` model has many associated `Post` models: + +```go +type User struct { + orm.Model + Name string + Posts []*Post +} + +type Post struct { + orm.Model + UserID uint + Name string +} +``` + +### Create or Update Associations + +You can use the `Select`, `Omit` methods to to control the create and update of associations. These two method cannot be used at the same time and the associated control functions are only applicable to `Create`, `Update`, `Save`: + +```go +user := models.User{Name: "user", Posts: []*models.Post{{Name: "post"}}} + +// Create all child associations while creating User +facades.Orm().Query().Select(orm.Associations).Create(&user) + +// Only create Post while creating User. Note: If you don't use `orm.Associations`, but customize specific child associations separately, all fields in the parent model should also be listed at this time. +facades.Orm().Query().Select("Name", "Posts").Create(&user) + +// When creating a User, ignore the Post, but create all other child associations +facades.Orm().Query().Omit("Posts").Create(&user) + +// When creating User, ignore Name field, but create all child associations +facades.Orm().Query().Omit("Name").Create(&user) + +// When creating User, ignore Name field and all child associations +facades.Orm().Query().Omit("Name", orm.Associations).Create(&user) +``` + +### Find Associations + +```go +// Find all matching related records +var posts []models.Post +facades.Orm().Query().Model(&user).Association("Posts").Find(&posts) + +// Find associations with conditions +facades.Orm().Query().Model(&user).Where("name = ?", "goravel").Order("id desc").Association("Posts").Find(&posts) +``` + +### Append Associations + +Append new associations for `Many To Many`, `One To Many`, replace current association for `One To One`, `One To One(revers)`: + +```go +facades.Orm().Query().Model(&user).Association("Posts").Append([]*models.Post{Post1, Post2}) + +facades.Orm().Query().Model(&user).Association("Posts").Append(&models.Post{Name: "goravel"}) +``` + +### Replace Associations + +Replace current associations with new ones: + +```go +facades.Orm().Query().Model(&user).Association("Posts").Replace([]*models.Post{Post1, Post2}) + +facades.Orm().Query().Model(&user).Association("Posts").Replace(models.Post{Name: "goravel"}, Post2) +``` + +### Delete Associations + +Remove the relationship between source & arguments if exists, only delete the reference, won’t delete those objects from DB, the foreign key must be NULL: + +```go +facades.Orm().Query().Model(&user).Association("Posts").Delete([]*models.Post{Post1, Post2}) + +facades.Orm().Query().Model(&user).Association("Posts").Delete(Post1, Post2) +``` + +### Clear Associations + +Remove all reference between source & association, won’t delete those associations: + +```go +facades.Orm().Query().Model(&user).Association("Posts").Clear() +``` + +### Count Associations + +Return the count of current associations: + +```go +facades.Orm().Query().Model(&user).Association("Posts").Count() + +// Count with conditions +facades.Orm().Query().Model(&user).Where("name = ?", "goravel").Association("Posts").Count() +``` + +### Batch Data + +```go +// Find all roles for all users +facades.Orm().Query().Model(&users).Association("Posts").Find(&posts) + +// Delete User A from all user's Posts +facades.Orm().Query().Model(&users).Association("Posts").Delete(&userA) + +// Get distinct count of all users' Posts +facades.Orm().Query().Model(&users).Association("Posts").Count() + +// For `Append`, `Replace` with batch data, the length of the arguments needs to be equal to the data's length or else it will return an error +var users = []models.User{user1, user2, user3} + +// We have 3 users, Append userA to user1's team, append userB to user2's team, append userA, userB and userC to user3's team +facades.Orm().Query().Model(&users).Association("Team").Append(&userA, &userB, &[]models.User{userA, userB, userC}) + +// Reset user1's team to userA,reset user2's team to userB, reset user3's team to userA, userB and userC +facades.Orm().Query().Model(&users).Association("Team").Replace(&userA, &userB, &[]models.User{userA, userB, userC}) +``` + +## Eager Loading + +Eager loading conveniences for querying multiple models, and alleviates the "N + 1" query problem. To illustrate the N + 1 query problem, consider a `Book` model that "belongs to" an `Author` model: + +```go +type Author struct { + orm.Model + Name string +} + +type Book struct { + orm.Model + AuthorID uint + Name string + Author *Author +} +``` + +Now, let's retrieve all books and their authors: + +```go +var books []models.Book +facades.Orm().Query().Find(&books) + +for _, book := range books { + var author models.Author + facades.Orm().Query().Find(&author, book.AuthorID) +} +``` + +To retrieve all the books in the database table along with their authors, the loop code executes a query for each book. This means that for a collection of 25 books, the loop would run 26 queries - one for the collection of books and 25 more to get the author of each book. + +However, we can simplify this process using eager loading. By using the `With` method, we can specify which relationships need to be eagerly loaded and reduce the number of queries to just two. + +```go +var books []models.Book +facades.Orm().Query().With("Author").Find(&books) + +for _, book := range books { + fmt.Println(book.Author) +} +``` + +For this operation, only two queries will be executed - one query to retrieve all books and one query to retrieve authors for all of the books: + +```sql +select * from `books`; + +select * from `authors` where `id` in (1, 2, 3, 4, 5, ...); +``` + +### Eager Loading Multiple Relationships + +Sometimes you may need to eager load several different relationships. To do so, just call the `With` method multiple times: + +```go +var book models.Book +facades.Orm().Query().With("Author").With("Publisher").Find(&book) +``` + +### Nested Eager Loading + +To eager load a relationship's relationships, you may use "dot" syntax. For example, let's eager load all of the book's authors and all of the author's personal contacts: + +```go +var book models.Book +facades.Orm().Query().With("Author.Contacts").Find(&book) +``` + +### Constraining Eager Loads + +Sometimes you may wish to eager load a relationship but also specify additional query conditions for the eager loading query. You can accomplish this as below: + +```go +import "github.com/goravel/framework/contracts/database/orm" + +var book models.Book +facades.Orm().Query().With("Author", "name = ?", "author").Find(&book) + +facades.Orm().Query().With("Author", func(query orm.Query) orm.Query { + return query.Where("name = ?", "author") +}).Find(&book) +``` + +In this example, Orm will only eager load posts where the post's `name` column equals the word `author`. + +### Lazy Eager Loading + +Sometimes you may need to eager load a relationship after the parent model has already been retrieved. For example, this may be useful if you need to dynamically decide whether to load related models: + +```go +var books []models.Book +facades.Orm().Query().Find(&books) + +for _, book := range books { + if someCondition { + err := facades.Orm().Query().Load(&book, "Author") + } +} +``` + +If you need to set additional query constraints on the eager loading query, you can use the code below: + +```go +import "github.com/goravel/framework/contracts/database/orm" + +var book models.Book +facades.Orm().Query().Load(&book, "Author", "name = ?", "author").Find(&book) + +facades.Orm().Query().Load(&book, "Author", func(query orm.Query) orm.Query { + return query.Where("name = ?", "author") +}).Find(&book) +``` + +To load a relationship only when it has not already been loaded, use the `LoadMissing` method: + +```go +facades.Orm().Query().LoadMissing(&book, "Author") +``` From ada879436b8cb5528de083b23782ffd8ea86458d Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:34 +0800 Subject: [PATCH 034/163] New translations authentication.md (Uzbek) [skip ci] Update translations (Uzbek) authentication.md --- uz_UZ/security/authentication.md | 177 +++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 uz_UZ/security/authentication.md diff --git a/uz_UZ/security/authentication.md b/uz_UZ/security/authentication.md new file mode 100644 index 000000000..edf9ea084 --- /dev/null +++ b/uz_UZ/security/authentication.md @@ -0,0 +1,177 @@ +# Authentication + +[[toc]] + +## Introduction + +Authentication is an indispensable feature in Web Applications, the `facades.Auth()` module of Goravel provides support for JWT and Session drivers, and you can customize the driver and user provider. + +## Configuration + +You can configure `defaults` guard and multiple `guards` in the `config/auth.go` file to switch different user identities in the application. + +You can configure the parameters of JWT in the `config/jwt.go` file, such as `secret`, `ttl`, `refresh_ttl`. + +### Different JWT Guard supports different configurations + +You can set TTL, Secret and RefreshTTL for each Guard separately in the `config/auth.go` file, if not set, these three configurations are used by the `config/jwt.go` file as default. + +```go +// config/auth.go +"guards": map[string]any{ + "user": map[string]any{ + "driver": "jwt", +++ "ttl": 60, +++ "refresh_ttl": 0, +++ "secret": "your-secret", + }, +}, +``` + +## Generate JWT Token + +```shell +./artisan jwt:secret +``` + +## Generate Token Using User + +You can generate a token by Model, there is no extra configuration if the model uses `orm.Model`, otherwise, you need to configure Tag on the model primary key field, for example: + +```go +type User struct { + ID uint `gorm:"primaryKey"` + Name string +} + +var user models.User +user.ID = 1 + +token, err := facades.Auth(ctx).Login(&user) +``` + +## Generate Token Using ID + +```go +token, err := facades.Auth(ctx).LoginUsingID(1) +``` + +## Parse Token + +```go +payload, err := facades.Auth(ctx).Parse(token) +``` + +Through `payload` you can get: + +1. `Guard`: Current Guard; +2. `Key`: User flag; +3. `ExpireAt`: Expire time; +4. `IssuedAt`: Issued time; + +> If `err` isn't nil other than `ErrorTokenExpired`, the payload should be nil. + +You can judge whether the Token is expired by err: + +```go +"errors" +"github.com/goravel/framework/auth" + +errors.Is(err, auth.ErrorTokenExpired) +``` + +> The token can be parsed normally with or without the Bearer prefix. + +## Get User + +You need to generate a Token by `Parse` before getting a user, the process can be handled in HTTP middleware. + +```go +var user models.User +err := facades.Auth(ctx).User(&user) // Must point +id, err := facades.Auth(ctx).ID() +``` + +## Refresh Token + +You need to generate a Token by `Parse` before refreshing the user. + +```go +token, err := facades.Auth(ctx).Refresh() +``` + +## Logout + +```go +err := facades.Auth(ctx).Logout() +``` + +## Multiple Guards + +```go +token, err := facades.Auth(ctx).Guard("admin").LoginUsingID(1) +err := facades.Auth(ctx).Guard("admin").Parse(token) +token, err := facades.Auth(ctx).Guard("admin").User(&user) +``` + +> When the default guard is not used, the `Guard` method must be called before calling the above methods. + +## Custom Driver + +### Add Custom Guard + +You can use the `facades.Auth().Extend()` method to define your own authentication guard, this method can be called in the `Boot` method of `AuthServiceProvider`. + +```go +import "github.com/goravel/framework/contracts/auth" + +func (receiver *AuthServiceProvider) Boot(app foundation.Application) { + facades.Auth().Extend("custom-driver", func(ctx http.Context, name string, userProvider auth.UserProvider) (auth.GuardDriver, error) { + return &CustomGuard{}, nil + }) +} +``` + +After defining the custom guard, you can reference it in the `guards` configuration of the `auth.go` file: + +```go +"guards": map[string]any{ + "api": map[string]any{ + "driver": "custom-driver", + "provider": "users", + }, +}, +``` + +### Add Custom UserProvider + +You can use the `facades.Auth().Provider()` method to define your own user provider, this method can also be called in the `Boot` method of `AuthServiceProvider`. + +```go +import "github.com/goravel/framework/contracts/auth" + +facades.Auth().Provider("custom-provider", func(ctx http.Context) (auth.UserProvider, error) { + return &UserProvider{}, nil +}) +``` + +After using the `Provider` method to register the provider, you can use the custom user provider in the `auth.go` configuration file. First, define a `provider` that uses the new driver: + +```go +"providers": map[string]any{ + "users": map[string]any{ + "driver": "custom-provider", + }, +}, +``` + +Finally, you can reference this provider in the `guards` configuration: + +```go +"guards": map[string]any{ + "api": map[string]any{ + "driver": "custom-provider", + "provider": "users", + }, +}, +``` From cbc5e03e5a2c344220eaf51896b183440c19c3ea Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:35 +0800 Subject: [PATCH 035/163] New translations authorization.md (Uzbek) [skip ci] Update translations (Uzbek) authorization.md --- uz_UZ/security/authorization.md | 196 ++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 uz_UZ/security/authorization.md diff --git a/uz_UZ/security/authorization.md b/uz_UZ/security/authorization.md new file mode 100644 index 000000000..a837477f0 --- /dev/null +++ b/uz_UZ/security/authorization.md @@ -0,0 +1,196 @@ +# Authorization + +[[toc]] + +## Introduction + +Goravel offers built-in [authentication](./authentication.md) services and an easy-to-use authorization feature to manage user actions on resources. Even if a user is authenticated, they may not have the authority to modify or delete certain Eloquent models or database records. Goravel's authorization feature allows for a systematic way of managing these authorization checks. + +There are two ways to authorize actions in Goravel: [gates](#Gates) and [policies](#Policies). Imagine gates and policies as similar to routes and controllers. Gates are based on closures and provide a simple approach to authorization, whereas policies group logic around a specific resource, similar to controllers. This documentation will first cover gates and then delve into policies. + +It's not necessary to exclusively use gates or policies when building an application. Most applications will use a combination of both, which is perfectly acceptable! + +## Gates + +### Writing Gates + +Gates serve as closures that verify whether a user is authorized to perform a specific action. They are commonly set up in the `bootstrap/app.go::WithCallback` function using the Gate facade. + +In this scenario, we will establish a gate to check if a user can modify a particular Post model by comparing its ID to the user_id of the post's creator. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithConfig(config.Boot). + WithCallback(func() { + facades.Gate().Define("update-post", + func(ctx context.Context, arguments map[string]any) contractsaccess.Response { + user := ctx.Value("user").(models.User) + post := arguments["post"].(models.Post) + + if user.ID == post.UserID { + return access.NewAllowResponse() + } else { + return access.NewDenyResponse("error") + } + }, + ) + }). + Create() +} +``` + +### Authorizing Actions + +To authorize an action using gates, you should use the `Allows` or `Denies` methods provided by the Gate facade: + +```go +package controllers + +import ( + "goravel/app/facades" +) + +type UserController struct { + +func (r *UserController) Show(ctx http.Context) http.Response { + var post models.Post + if facades.Gate().Allows("update-post", map[string]any{ + "post": post, + }) { + + } +} +``` + +You can authorize multiple actions simultaneously using the `Any` or `None` methods. + +```go +if facades.Gate().Any([]string{"update-post", "delete-post"}, map[string]any{ + "post": post, +}) { + // The user can update or delete the post... +} + +if facades.Gate().None([]string{"update-post", "delete-post"}, map[string]any{ + "post": post, +}) { + // The user can't update or delete the post... +} +``` + +### Gate Responses + +The `Allows` method returns a boolean value. To get the full authorization response, use the `Inspect` method. + +```go +response := facades.Gate().Inspect("edit-settings", nil); + +if response.Allowed() { + // The action is authorized... +} else { + fmt.Println(response.Message()) +} +``` + +### Intercepting Gate Checks + +Sometimes, you may wish to grant all abilities to a specific user. You can define a closure using the `Before` method, which runs before any other authorization checks: + +```go +facades.Gate().Before(func(ctx context.Context, ability string, arguments map[string]any) contractsaccess.Response { + user := ctx.Value("user").(models.User) + if isAdministrator(user) { + return access.NewAllowResponse() + } + + return nil +}) +``` + +If the `Before` closure returns a non-nil result, that result will be considered the result of the authorization check. + +The `After` method can be used to define a closure that will be executed after all other authorization checks. + +```go +facades.Gate().After(func(ctx context.Context, ability string, arguments map[string]any, result contractsaccess.Response) contractsaccess.Response { + user := ctx.Value("user").(models.User) + if isAdministrator(user) { + return access.NewAllowResponse() + } + + return nil +}) +``` + +> Notice: The return result of `After` will be applied only when `facades.Gate().Define` returns nil. + +### Inject Context + +The `context` will be passed to the `Before`, `After`, and `Define` methods. + +```go +facades.Gate().WithContext(ctx).Allows("update-post", map[string]any{ + "post": post, +}) +``` + +## Policies + +### Generating Policies + +You can use the `make:policy` Artisan command to generate a policy. The generated policy will be saved in the `app/policies` directory. If the directory does not exist in your application, Goravel will create it for you. + +```shell +./artisan make:policy PostPolicy +./artisan make:policy user/PostPolicy +``` + +### Writing Policies + +Let's define an `Update` method on `PostPolicy` to check if a `User` can update a `Post`. + +```go +package policies + +import ( + "context" + "goravel/app/models" + + "github.com/goravel/framework/auth/access" + contractsaccess "github.com/goravel/framework/contracts/auth/access" +) + +type PostPolicy struct { +} + +func NewPostPolicy() *PostPolicy { + return &PostPolicy{} +} + +func (r *PostPolicy) Update(ctx context.Context, arguments map[string]any) contractsaccess.Response { + user := ctx.Value("user").(models.User) + post := arguments["post"].(models.Post) + + if user.ID == post.UserID { + return access.NewAllowResponse() + } else { + return access.NewDenyResponse("You do not own this post.") + } +} +``` + +Then we can register the policy to the `bootstrap/app.go::WithCallback` function: + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithConfig(config.Boot). + WithCallback(func() { + facades.Gate().Define("update-post", policies.NewPostPolicy().Update) + }). + Create() +} +``` + +As you work on authorizing different actions, you can add more methods to your policy. For instance, you can create `View` or `Delete` methods to authorize various model-related actions. Feel free to name your policy methods as you see fit. From c72e24524edc4b06e3d382e904381ce7dbc9507a Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:36 +0800 Subject: [PATCH 036/163] New translations encryption.md (Uzbek) [skip ci] Update translations (Uzbek) encryption.md --- uz_UZ/security/encryption.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 uz_UZ/security/encryption.md diff --git a/uz_UZ/security/encryption.md b/uz_UZ/security/encryption.md new file mode 100644 index 000000000..6675e72b4 --- /dev/null +++ b/uz_UZ/security/encryption.md @@ -0,0 +1,29 @@ +# Encryption + +[[toc]] + +## Introduction + +Goravel's encryption services provide a simple, convenient interface for encrypting and decrypting text via OpenSSL using AES-256 encryption. All of Goravel's encrypted values are signed using a message authentication code (GMAC) so that their underlying value can not be modified or tampered with once encrypted. + +## Configuration + +Before using Goravel's encrypter, you must set the `key` configuration option in your `config/app.go` configuration file. This option is driven by the `APP_KEY` environment variable. Use the `./artisan key:generate` command to generate this variable's value since the `key:generate` command will utilize Golang's secure random bytes generator to create a secure cryptographic key for your application. + +## Using The Encrypter + +### Encrypting A Value + +To encrypt a value, you can use the `EncryptString` method in `facades.Crypt()`. This method encrypts values using the OpenSSL and AES-256-GCM cipher. Additionally, all encrypted values are signed with a message authentication code (GMAC) to prevent decryption by malicious users who try to tamper with the data. + +```go +secret, err := facades.Crypt().EncryptString("goravel") +``` + +### Decrypting A Value + +You can use the `DecryptString` method from `facades.Crypt()` to decrypt values. If the value can not be properly decrypted, such as when the message authentication code is invalid, an error will be returned. + +```go +str, err := facades.Crypt().DecryptString(secret) +``` From c0f822b02b5602ce35a243ffd78292915b102bad Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:37 +0800 Subject: [PATCH 037/163] New translations hashing.md (Uzbek) [skip ci] Update translations (Uzbek) hashing.md --- uz_UZ/security/hashing.md | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 uz_UZ/security/hashing.md diff --git a/uz_UZ/security/hashing.md b/uz_UZ/security/hashing.md new file mode 100644 index 000000000..2d6a38608 --- /dev/null +++ b/uz_UZ/security/hashing.md @@ -0,0 +1,41 @@ +# Hashing + +[[toc]] + +## Introduction + +The Goravel `facades.Hash()` provides secure Argon2id and Bcrypt hashing for storing user passwords. If you are using one of the Goravel application starter kits, Argon2id will be used for registration and authentication by default. + +## Configuration + +The default hashing driver for your application is configured in your application's `config/hashing.go` configuration file. There are currently several supported drivers: Argon2id and Bcrypt. + +## Basic Usage + +### Hashing Passwords + +You may hash a password by calling the `Make` method on the `facades.Hash()`: + +```go +password, err := facades.Hash().Make(password) +``` + +### Verifying That A Password Matches A Hash + +The `Check` method provided by the Hash facade allows you to verify that a given plain-text string corresponds to a given hash: + +```go +if facades.Hash().Check('plain-text', hashedPassword) { + // The passwords match... +} +``` + +### Determining If A Password Needs To Be Rehashed + +The `NeedsRehash` method provided by the Hash facade allows you to determine if the work factor used by the hasher has changed since the password was hashed. Some applications choose to perform this check during the application's authentication process: + +```go +if facades.Hash().NeedsRehash(hashed) { + hashed = facades.Hash().Make('plain-text'); +} +``` From 41b72872b33f9a0093d8982863330aedb99730ab Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:38 +0800 Subject: [PATCH 038/163] New translations getting-started.md (Uzbek) [skip ci] Update translations (Uzbek) getting-started.md --- uz_UZ/testing/getting-started.md | 295 +++++++++++++++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 uz_UZ/testing/getting-started.md diff --git a/uz_UZ/testing/getting-started.md b/uz_UZ/testing/getting-started.md new file mode 100644 index 000000000..b7df31076 --- /dev/null +++ b/uz_UZ/testing/getting-started.md @@ -0,0 +1,295 @@ +# Getting Started + +[[toc]] + +## Introduction + +The testing function of Goravel relies on Golang's official test component, extending unit testing to support integration testing and improve application robustness. + +## Environment + +### Custom Environment File + +By default, the `.env` file in the root directory is used to inject configuration information during testing. If you want to use different `.env` files for different packages, you can create a `.env` file in the package directory, and the test will read this file first. + +``` +- /app +- /config +- ... +- /test + - /feature + - .env + - user_test.go +- .env +``` + +In addition, you may create a `.env.testing` file at the root of your project. This file will be used instead of the `.env` file when running `go test` with the `--env` option, note that this option needs to follow the test directory, for example: + +```shell +go test ./... --env=.env.testing +go test ./... -e=.env.testing +``` + +### `TestCase` Struct + +There is a `TestCase` Struct in Goravel, and the Struct will provide some convenient test methods in the future, in addition, there is an `init` method in the same file, this method guides the registration of the Goravel application before running the test. You may include any necessary logic in this method that needs to be executed before the test. + +## Creating Tests + +To create a new test case, use the `make:test` Artisan command: + +```shell +./artisan make:test feature/UserTest +``` + +Our test cases are written using the suite function of the [stretchr/testify](https://github.com/stretchr/testify) package by default. This function enables us to configure pre-test, post-test, sub-test, and assertion, among other things, which results in more organized test cases. For further information, kindly refer to the official documentation. + +```go +package feature + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "goravel/tests" +) + +type ExampleTestSuite struct { + suite.Suite + tests.TestCase +} + +func TestExampleTestSuite(t *testing.T) { + suite.Run(t, new(ExampleTestSuite)) +} + +// SetupTest will run before each test in the suite. +func (s *ExampleTestSuite) SetupTest() { +} + +// TearDownTest will run after each test in the suite. +func (s *ExampleTestSuite) TearDownTest() { +} + +func (s *ExampleTestSuite) TestIndex() { + s.True(true) +} +``` + +## Database Testing + +Goravel model factories and Seeders can easily create test database records for the application's model. + +### Factories + +If you're conducting tests, it might be necessary to add some records to your database before running the test. You don't have to manually input the values of each column for the test data creation. With Goravel, you can set default attributes for your models via [factories](../orm/factories.md). + +```go +var user models.User +err := facades.Orm().Factory().Create(&user) +``` + +### Running Seeders + +If you would like to use [database seeders](../database/seeding.md) to populate your database during a feature test, you may invoke the `Seed` method. By default, the `Seed` method will execute the `DatabaseSeeder`, which should execute all of your other seeders. Alternatively, you can pass a specific seeder struct to the `Seed` method: + +```go +package feature + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "goravel/database/seeders" + "goravel/tests" +) + +type ExampleTestSuite struct { + suite.Suite + tests.TestCase +} + +func TestExampleTestSuite(t *testing.T) { + suite.Run(t, new(ExampleTestSuite)) +} + +// SetupTest will run before each test in the suite. +func (s *ExampleTestSuite) SetupTest() { +} + +// TearDownTest will run after each test in the suite. +func (s *ExampleTestSuite) TearDownTest() { +} + +func (s *ExampleTestSuite) TestIndex() { + // Run the DatabaseSeeder... + s.Seed() + + // Run multiple specific seeders... + s.Seed(&seeders.UserSeeder{}, &seeders.PhotoSeeder{}) +} +``` + +### Using Docker + +When using `go test`, multiple packages are tested in parallel. As a result, refreshing the database or cache in a test case using a local database or cache can potentially affect other parallel test cases. To address this, Goravel offers Docker-based testing. With Docker, a database or cache image can be created and used independently across different packages. + +> Due to the limited support of the Docker image for the windows system, currently, the Docker test can only be run in non-windows environments. + +#### Initiate Docker + +You can use the `Database` or `Cache` method to create an image, or you can pass the connection name to this method: + +```go +database, err := facades.Testing().Docker().Database() +database, err := facades.Testing().Docker().Database("postgres") + +cache, err := facades.Testing().Docker().Cache() +cache, err := facades.Testing().Docker().Cache("redis") +``` + +You can also use the `Image` method to customize the image: + +```go +import contractstesting "github.com/goravel/framework/contracts/testing" + +image, err := facades.Testing().Docker().Image(contractstesting.Image{ + Repository: "mysql", + Tag: "5.7", + Env: []string{ + "MYSQL_ROOT_PASSWORD=123123", + "MYSQL_DATABASE=goravel", + }, + ExposedPorts: []string{"3306"}, +}) +``` + +#### Build Image + +After the image is initiated, you can use the `Build` method to build the image: + +```go +err := database.Build() +err := cache.Build() +``` + +At this time, you can use the `docker ps` command to see that the image is already running on the system, and you can obtain the configuration information of the database through the `Config` method to facilitate connection debugging: + +```go +config := database.Config() +config := cache.Config() +``` + +#### Running Seeders + +If you wish to use [seeder](../database/seeding.md) to populate the database during testing, you can call the `Seed` method. By default, the `Seed` method will execute the `DatabaseSeeder`, which should execute all of your other seeders. Alternatively, you can pass a specific seeder struct to the `Seed` method: + +```go +err := database.Seed() +err := database.Seed(&seeders.UserSeeder{}) +``` + +#### Refresh Database or Cache + +Because the test cases in the same package are executed serially, refreshing the database or cache after a single test case run will have no negative impact, we can use the `Fresh` method: + +```go +err := database.Fresh() +err := cache.Fresh() +``` + +For the database, you can also use the `RefreshDatabase` method: + +```go +package feature + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "goravel/tests" +) + +type ExampleTestSuite struct { + suite.Suite + tests.TestCase +} + +func TestExampleTestSuite(t *testing.T) { + suite.Run(t, new(ExampleTestSuite)) +} + +// SetupTest will run before each test in the suite. +func (s *ExampleTestSuite) SetupTest() { + s.RefreshDatabase() +} + +// TearDownTest will run after each test in the suite. +func (s *ExampleTestSuite) TearDownTest() { +} + +func (s *ExampleTestSuite) TestIndex() { +} +``` + +#### Uninstall Image + +After the test cases in the sub-package are executed, the image will be uninstalled automatically in one hour, you can also use the `Shutdown` method to uninstall the image manually. + +```go +err := database.Shutdown() +``` + +#### Example + +We can create a `TestMain` method in the sub-package and add the pre-logic of the test case: + +```go +// tests/feature/main_test.go +package feature + +import ( + "fmt" + "os" + "testing" + + "goravel/app/facades" + "goravel/database/seeders" +) + +func TestMain(m *testing.M) { + database, err := facades.Testing().Docker().Database() + if err != nil { + panic(err) + } + + if err := database.Build(); err != nil { + panic(err) + } + if err := database.Ready(); err != nil { + panic(err) + } + if err := database.Migrate(); err != nil { + panic(err) + } + + if err := facades.App().Restart(); err != nil { + panic(err) + } + + // Execute test cases + exit := m.Run() + + // Uninstall the image after all test cases have been run + if err := database.Shutdown(); err != nil { + panic(err) + } + + os.Exit(exit) +} +``` + +> For more usage of the TestMain method, see [Official Documentation](https://pkg.go.dev/testing#hdr-Main). From 65d79e5d3827834d17963f08f19021f623f4384c Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:40 +0800 Subject: [PATCH 039/163] New translations http-tests.md (Uzbek) [skip ci] Update translations (Uzbek) http-tests.md --- uz_UZ/testing/http-tests.md | 588 ++++++++++++++++++++++++++++++++++++ 1 file changed, 588 insertions(+) create mode 100644 uz_UZ/testing/http-tests.md diff --git a/uz_UZ/testing/http-tests.md b/uz_UZ/testing/http-tests.md new file mode 100644 index 000000000..afd5cca61 --- /dev/null +++ b/uz_UZ/testing/http-tests.md @@ -0,0 +1,588 @@ +# HTTP Tests + +[[toc]] + +## Introduction + +When building web applications, you'll often need to test if your HTTP requests work correctly from start to finish. Goravel's testing tools make this straightforward - you can simulate requests and verify responses without setting up complex test environments. + +## Make Requests + +Testing HTTP endpoints in Goravel uses a simple pattern. Start with the `Http` method from your `TestCase`, which needs a `*testing.T` parameter for assertions. This gives you a request object (`framework/contracts/testing.TestRequest`) that handles all common HTTP verbs like `Get`, `Post`, and `Put`. + +Instead of making real HTTP calls, these methods simulate your application's request cycle internally. Each request returns a response object (`framework/contracts/testing.TestResponse`) with methods to check the results. + +Here's a basic example: + +```go +func (s *ExampleTestSuite) TestIndex() { + response, err := s.Http(s.T()).Get("/users/1") + s.Nil(err) + response.AssertStatus(200) +} +``` + +### Customize Request Headers + +You can customize request headers using either `WithHeader` for a single header or `WithHeaders` for multiple headers: + +```go +func (s *ExampleTestSuite) TestIndex() { + // Single header + response, err := s.Http(s.T()).WithHeader("X-Custom-Header", "Value").Get("/users/1") + + // Multiple headers + response, err := s.Http(s.T()).WithHeaders(map[string]string{ + "X-Custom-Header": "Value", + "Accept": "application/json", + }).Get("/users/1") +} +``` + +### Cookies + +You may use either `WithCookie` or `WithCookies` method to set cookies value before making a request. + +```go +import "github.com/goravel/framework/testing/http" + +func (s *ExampleTestSuite) TestIndex() { + response, err := s.Http(s.T()).WithCookie(http.Cookie("name", "krishan")).Get("/users/1") + + // or use WithCookies for multiple Cookies + response, err := s.Http(s.T()).WithCookies(http.Cookies(map[string]string{ + "name": "krishan", + "lang": "en", + })).Get("/users/1") +} +``` + +### WithSession + +You may set the data to the session using the `WithSession` method: + +```go +func (s *ExampleTestSuite) TestIndex() { + response, err := s.Http(s.T()).WithSession(map[string]any{"role": "admin"}).Get("/users/1") +} +``` + +### Debugging Responses + +After making request you may use `Session`, `Headers`, `Content`, `Cookies` or `Json` method to check data returned from the request. + +```go +func (s *ExampleTestSuite) TestIndex() { + response, err := s.Http(s.T()).WithSession(map[string]any{"role": "admin"}).Get("/users/1") + + content, err := response.Content() + + cookies := response.Cookies() + + headers := response.Headers() + + json, err := response.Json() // response body parsed as json(map[string]any) + + session, err := response.Session() // returns all values stored in the current request session +} +``` + +## Building Body + +For method like `Post`, `Put`, `Delete` etc. Goravel accepts `io.Reader` as second argument. To simplify building payloads, the framework provides utility methods for constructing request bodies. + +```go +import "github.com/goravel/framework/support/http" + +func (s *ExampleTestSuite) TestIndex() { + builder := http.NewBody().SetField("name", "krishan") + + body, err := builder.Build() + + response, err := s.Http(s.T()).WithHeader("Content-Type", body.ContentType()).Post("/users", body) +} +``` + +## Testing Json APIs + +Goravel provides several helpers to test JSON API responses effectively. It attempts to unmarshal the response body into a Go `map[string]any`. If unmarshalling fails, the associated assertions will also fail. + +```go +func (s *ExampleTestSuite) TestIndex() { + response, err := s.Http(s.T()).WithHeader("Content-Type", body.ContentType()).Post("/users", nil) + s.Nil(err) + + response.AssertStatus(201). + AssertJson(map[string]any{ + "created": true, + }) +} +``` + +To access the unmarshalled JSON directly, use the `Json` method on the `TestResponse`. This lets you inspect individual elements of the response body. + +```go +json, err := response.Json() +s.Nil(err) +s.True(json["created"]) +``` + +:::tip +The `AssertJson` method checks whether the response contains all the specified values, even if the response includes additional fields. It doesn't require an exact match unless you use `AssertExactJson`. +::: + +### Asserting Exact JSON Matches + +If you need to verify that the response matches your expected JSON exactly (with no extra or missing fields), use the `AssertExactJson` method. + +```go +func (s *ExampleTestSuite) TestIndex() { + response, err := s.Http(s.T()).WithHeader("Content-Type", body.ContentType()).Post("/users", nil) + s.Nil(err) + + response.AssertStatus(201). + AssertExactJson(map[string]any{ + "created": true, + }) +} +``` + +### Fluent JSON Testing + +Goravel makes it easy to perform fluent assertions on JSON responses. Using the `AssertFluentJson` method, you can pass a closure that provides an instance of `framework/contracts/testing.AssertableJSON`. This instance allows you to check specific values or conditions in the JSON response returned by your request. + +For example, you can use the `Where` method to assert that a particular value exists in the JSON response, and the `Missing` method to ensure that an attribute is not present. + +```go +import contractstesting "github.com/goravel/framework/contracts/testing" + +func (s *ExampleTestSuite) TestIndex() { + response, err := s.Http(s.T()).Get("/users/1") + s.Nil(err) + + response.AssertStatus(201). + AssertFluentJson(func (json contractstesting.AssertableJSON) { + json.Where("id", float64(1)). + Where("name", "bowen"). + WhereNot("lang", "en"). + Missing("password") + }) +} +``` + +### Asserting Attribute Presence / Absence + +If you want to check whether an attribute is present or missing, Goravel makes it simple with the `Has` and `Missing` methods. + +```go +response.AssertStatus(201). + AssertFluentJson(func (json contractstesting.AssertableJSON) { + json.Has("username"). + Missing("password") + }) +``` + +You can also assert the presence or absence of multiple attributes at once using `HasAll` and `MissingAll`. + +```go +response.AssertStatus(201). + AssertFluentJson(func (json contractstesting.AssertableJSON) { + json.Has([]string{"username", "email"}). + MissingAll([]string{"verified", "password"}) + }) +``` + +If you only need to check for the presence of at least one attribute from a list, use the `HasAny` method. + +```go +response.AssertStatus(201). + AssertFluentJson(func (json contractstesting.AssertableJSON) { + json.HasAny([]string{"username", "email"}) + }) +``` + +### Scoping JSON Collection Assertions + +When a response contains a collection of objects under a named key, you can use various methods to assert its structure and content. + +```go +type Item struct { + ID int `json:"id"` +} + +facades.Route().Get("/", func(ctx http.Context) http.Response { + items := []Item{ + {ID: 1}, + {ID: 2}, + } + return ctx.Response().Json(200, map[string]{ + "items": items, + }) +} +``` + +You can use the `Count` method to verify the number of elements in the collection. To assert properties of the first element, use the `First` method, which provides an instance of `AssertableJson`. Similarly, the `Each` method allows you to iterate over all elements and assert their properties individually. Alternatively, the `HasWithScope` method combines the functionality of `First` and `Count`, allowing you to assert both the first element and its contents while providing an `AssertableJson` instance for scoped assertions. + +```go +// Count and First +response.AssertStatus(200). + AssertFluentJson(func(json contractstesting.AssertableJSON) { + json.Count("items", 2). + First("items", func(json contractstesting.AssertableJSON) { + json.Where("id", 1) + }) + }) + +// Each +response.AssertStatus(200). + AssertFluentJson(func(json contractstesting.AssertableJSON) { + json.Count("items", 2). + Each("items", func(json contractstesting.AssertableJSON) { + json.Has("id") + }) + }) + +// HasWithScope +response.AssertStatus(200). + AssertFluentJson(func(json contractstesting.AssertableJSON) { + json.HasWithScope("items", 2, func(json contractstesting.AssertableJSON) { + json.Where("id", 1) + }) + }) +``` + +## Available Assertions + +### Response Assertions + +| | | | +| ------------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------- | +| [AssertAccepted](#assertaccepted) | [AssertBadRequest](#assertbadrequest) | [AssertConflict](#assertconflict) | +| [AssertCookie](#assertcookie) | [AssertCookieExpired](#assertcookieexpired) | [AssertCookieMissing](#assertcookiemissing) | +| [AssertCookieNotExpired](#assertcookienotexpired) | [AssertCreated](#assertcreated) | [AssertDontSee](#assertdontsee) | +| [AssertExactJson](#assertexactjson) | [AssertFluentJson](#assertfluentjson) | [AssertForbidden](#assertforbidden) | +| [AssertFound](#assertfound) | [AssertGone](#assertgone) | [AssertHeader](#assertheader) | +| [AssertHeaderMissing](#assertheadermissing) | [AssertInternalServerError](#assertinternalservererror) | [AssertJson](#assertjson) | +| [AssertJsonMissing](#assertjsonmissing) | [AssertMethodNotAllowed](#assertmethodnotallowed) | [AssertMovedPermanently](#assertmovedpermanently) | +| [AssertNoContent](#assertnocontent) | [AssertNotAcceptable](#assertnotacceptable) | [AssertNotFound](#assertnotfound) | +| [AssertNotModified](#assertnotmodified) | [AssertOk](#assertok) | [AssertPartialContent](#assertpartialcontent) | +| [AssertPaymentRequired](#assertpaymentrequired) | [AssertRequestTimeout](#assertrequesttimeout) | [AssertSee](#assertsee) | +| [AssertSeeInOrder](#assertseeinorder) | [AssertServerError](#assertservererror) | [AssertServiceUnavailable](#assertserviceunavailable) | +| [AssertStatus](#assertstatus) | [AssertSuccessful](#assertsuccessful) | [AssertTemporaryRedirect](#asserttemporaryredirect) | +| [AssertTooManyRequests](#asserttoomanyrequests) | [AssertUnauthorized](#assertunauthorized) | [AssertUnprocessableEntity](#assertunprocessableentity) | + +### AssertAccepted + +Asserts that the response has an `202 Accepted` HTTP status code: + +```go +response.AssertAccepted() +``` + +### AssertBadRequest + +Asserts that the response has a `400 Bad Request` HTTP status code: + +```go +response.AssertBadRequest() +``` + +### AssertConflict + +Asserts that the response has a `409 Conflict` HTTP status code: + +```go +response.AssertConflict() +``` + +### AssertCookie + +Asserts that the response contains a cookie with the specified name and value: + +```go +response.AssertCookie("name", "value") +``` + +### AssertCookieExpired + +Asserts that the specified cookie has expired: + +```go +response.AssertCookieExpired("name") +``` + +### AssertCookieMissing + +Asserts that the response does not contain a cookie with the specified name: + +```go +response.AssertCookieMissing("name") +``` + +### AssertCookieNotExpired + +Asserts that the specified cookie has not expired: + +```go +response.AssertCookieNotExpired("name") +``` + +### AssertCreated + +Asserts that the response has a `201 Created` HTTP status code: + +```go +response.AssertCreated() +``` + +### AssertDontSee + +Asserts that the response does not contain the specified values. The second parameter (optional) determines whether to escape special characters in the values before checking. If not provided, it defaults to true. + +```go +response.AssertDontSee([]string{"
"}, false) // Do not escape special characters +``` + +### AssertExactJson + +Asserts that the response JSON matches exactly the provided `map[string]any`: + +```go +response.AssertExactJson(map[string]any{"created": true}) +``` + +### AssertFluentJson + +Asserts the response JSON using a fluent interface: + +```go +import contractstesting "github.com/goravel/framework/contracts/testing" + +response.AssertFluentJson(func(json contractstesting.AssertableJSON) { + json.Where("created", true) +}) +``` + +### AssertForbidden + +Asserts that the response has a `403 Forbidden` HTTP status code: + +```go +response.AssertForbidden() +``` + +### AssertFound + +Asserts that the response has a `302 Found` HTTP status code: + +```go +response.AssertFound() +``` + +### AssertGone + +Asserts that the response has a `410 Gone` HTTP status code: + +```go +response.AssertGone() +``` + +### AssertHeader + +Asserts that the response contains the specified header with the given value: + +```go +response.AssertHeader("Content-Type", "application/json") +``` + +### AssertHeaderMissing + +Asserts that the response does not contain the specified header: + +```go +response.AssertHeaderMissing("X-Custom-Header") +``` + +### AssertInternalServerError + +Asserts that the response has a `500 Internal Server` Error HTTP status code: + +```go +response.AssertInternalServerError() +``` + +### AssertJson + +Asserts that the response JSON contains the provided fragment: + +```go +response.AssertJson(map[string]any{"created": true}) +``` + +### AssertJsonMissing + +Asserts that the specified keys or values are missing in the response JSON: + +```go +response.AssertJsonMissing(map[string]any{"created": false}) +``` + +### AssertMethodNotAllowed + +Asserts that the response has a `405 Method Not Allowed` HTTP status code: + +```go +response.AssertMethodNotAllowed() +``` + +### AssertMovedPermanently + +Asserts that the response has a `301 Moved Permanently` HTTP status code: + +```go +response.AssertMovedPermanently() +``` + +### AssertNoContent + +Asserts that the response has a `204 No Content` HTTP status code: + +```go +response.AssertNoContent() +``` + +### AssertNotAcceptable + +Asserts that the response has a `406 Not Acceptable` HTTP status code: + +```go +response.AssertNotAcceptable() +``` + +### AssertNotFound + +Asserts that the response has a `404 Not Found` HTTP status code: + +```go +response.AssertNotFound() +``` + +### AssertNotModified + +Asserts that the response has a `304 Not Modified` HTTP status code: + +```go +response.AssertNotModified() +``` + +### AssertOk + +Asserts that the response has a `200 OK` HTTP status code: + +```go +response.AssertOk() +``` + +### AssertPartialContent + +Asserts that the response has a `206 Partial Content` HTTP status code: + +```go +response.AssertPartialContent() +``` + +### AssertPaymentRequired + +Asserts that the response has a `402 Payment Required` HTTP status code: + +```go +response.AssertPaymentRequired() +``` + +### AssertRequestTimeout + +Asserts that the response has a `408 Request Timeout` HTTP status code: + +```go +response.AssertRequestTimeout() +``` + +### AssertSee + +Asserts that the response contains the specified values. The second parameter (optional) determines whether to escape special characters in the values before checking. If not provided, it defaults to `true`. + +```go +response.AssertSee([]string{"
"}, false) // Do not escape special characters +``` + +### AssertSeeInOrder + +Asserts that the response contains the specified values in the given order. The second parameter (optional) determines whether to escape special characters in the values before checking. If not provided, it defaults to `true`. + +```go +response.AssertSeeInOrder([]string{"First", "Second"}, false) // Do not escape special characters +``` + +### AssertServerError + +Asserts that the response has a server error (>= 500 , < 600) HTTP status code: + +```go +response.AssertServerError() +``` + +### AssertServiceUnavailable + +Asserts that the response has a `503 Service Unavailable` HTTP status code: + +```go +response.AssertServiceUnavailable() +``` + +### AssertStatus + +Asserts that the response has the specified HTTP status code: + +```go +response.AssertStatus(200) +``` + +### AssertSuccessful + +Asserts that the response has a successful HTTP status code (2xx): + +```go +response.AssertSuccessful() +``` + +### AssertTemporaryRedirect + +Asserts that the response has a `307 Temporary Redirect` HTTP status code: + +```go +response.AssertTemporaryRedirect() +``` + +### AssertTooManyRequests + +Asserts that the response has a `429 Too Many Requests` HTTP status code: + +```go +response.AssertTooManyRequests() +``` + +### AssertUnauthorized + +Asserts that the response has a `401 Unauthorized` HTTP status code: + +```go +response.AssertUnauthorized() +``` + +### AssertUnprocessableEntity + +Asserts that the response has a `422 Unprocessable Entity` HTTP status code: + +```go +response.AssertUnprocessableEntity() +``` From 4ebbc7a3fe71db661e05ea5abce70a0944be2098 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:41 +0800 Subject: [PATCH 040/163] New translations mock.md (Uzbek) [skip ci] Update translations (Uzbek) mock.md --- uz_UZ/testing/mock.md | 549 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 549 insertions(+) create mode 100644 uz_UZ/testing/mock.md diff --git a/uz_UZ/testing/mock.md b/uz_UZ/testing/mock.md new file mode 100644 index 000000000..4f96d1e4b --- /dev/null +++ b/uz_UZ/testing/mock.md @@ -0,0 +1,549 @@ +# Mock + +[[toc]] + +## Description + +All functions of Goravel are implemented using `facades`, and all `facades` are made up of interfaces. So with the mock function from [stretchr/testify](http://github.com/stretchr/testify), Goravel can deliver an exceptional testing experience. + +## Mock facades.App + +```go +import "github.com/goravel/framework/testing/mock" + +func CurrentLocale() string { + return facades.App().CurrentLocale(context.Background()) +} + +func TestCurrentLocale(t *testing.T) { + mockFactory := mock.Factory() + mockApp := mockFactory.App() + mockApp.On("CurrentLocale", context.Background()).Return("en").Once() + + assert.Equal(t, "en", CurrentLocale()) + mockApp.AssertExpectations(t) +} +``` + +## Mock facades.Artisan + +```go +func ArtisanCall() { + facades.Artisan().Call("list") +} + +func TestArtisan(t *testing.T) { + mockFactory := mock.Factory() + mockArticle := mockFactory.Artisan() + mockArticle.On("Call", "list").Once() + + assert.NotPanics(t, func() { + ArtisanCall() + }) + + mockArticle.AssertExpectations(t) +} +``` + +## Mock facades.Auth + +```go +import ( + "testing" + + "github.com/goravel/framework/http" + "github.com/goravel/framework/testing/mock" + "github.com/stretchr/testify/assert" + + "goravel/app/facades" +) + +func Auth() error { + return facades.Auth().Logout(http.Background()) +} + +func TestAuth(t *testing.T) { + mockFactory := mock.Factory() + mockAuth := mockFactory.Auth() + mockAuth.On("Logout", http.Background()).Return(nil).Once() + err := Auth() + + assert.Nil(t, err) + + mockAuth.AssertExpectations(t) +} +``` + +## Mock facades.Cache + +```go +import "github.com/goravel/framework/testing/mock" + +func Cache() string { + if err := facades.Cache().Put("name", "goravel", 1*time.Minute); err != nil { + fmt.Println("cache.put.error", err) + } + + return facades.Cache().Get("name", "test").(string) +} + +func TestCache(t *testing.T) { + mockFactory := mock.Factory() + mockCache := mockFactory.Cache() + + mockCache.On("Put", "name", "goravel", mock.Anything).Return(nil).Once() + mockCache.On("Get", "name", "test").Return("Goravel").Once() + + res := Cache() + assert.Equal(t, res, "Goravel") + + mockCache.AssertExpectations(t) +} +``` + +## Mock facades.Config + +```go +import "github.com/goravel/framework/testing/mock" + +func Config() string { + return facades.Config().GetString("app.name", "test") +} + +func TestConfig(t *testing.T) { + mockFactory := mock.Factory() + mockConfig := mockFactory.Config() + mockConfig.On("GetString", "app.name", "test").Return("Goravel").Once() + + res := Config() + assert.Equal(t, res, "Goravel") + + mockConfig.AssertExpectations(t) +} +``` + +## Mock facades.Crypt + +```go +import ( + "testing" + + "github.com/goravel/framework/testing/mock" + "github.com/stretchr/testify/assert" + + "goravel/app/facades" +) + +func Crypt(str string) (string, error) { + res, err := facades.Crypt().EncryptString(str) + if err != nil { + return "", err + } + + return facades.Crypt().DecryptString(res) +} + +func TestCrypt(t *testing.T) { + mockFactory := mock.Factory() + mockCrypt := mockFactory.Crypt() + mockCrypt.On("EncryptString", "Goravel").Return("test", nil).Once() + mockCrypt.On("DecryptString", "test").Return("Goravel", nil).Once() + + res, err := Crypt("Goravel") + assert.Equal(t, "Goravel", res) + assert.Nil(t, err) + + mockCrypt.AssertExpectations(t) +} +``` + +## Mock facades.Event + +```go +import "github.com/goravel/framework/testing/mock" + +func Event() error { + return facades.Event().Job(&events.TestEvent{}, []contractevent.Arg{ + {Type: "string", Value: "abcc"}, + {Type: "int", Value: 1234}, + }).Dispatch() +} + +func TestEvent(t *testing.T) { + mockFactory := mock.Factory() + mockEvent := mockFactory.Event() + mockTask := mockFactory.EventTask() + mockEvent.On("Job", mock.Anything, mock.Anything).Return(mockTask).Once() + mockTask.On("Dispatch").Return(nil).Once() + + assert.Nil(t, Event()) + + mockEvent.AssertExpectations(t) + mockTask.AssertExpectations(t) +} +``` + +## Mock facades.Gate + +```go +import ( + "testing" + + "github.com/goravel/framework/testing/mock" + "github.com/stretchr/testify/assert" + + "goravel/app/facades" +) + +func Gate() bool { + return facades.Gate().Allows("update-post", map[string]any{ + "post": "test", + }) +} + +func TestGate(t *testing.T) { + mockFactory := mock.Factory() + mockGate := mockFactory.Gate() + mockGate.On("Allows", "update-post", map[string]any{ + "post": "test", + }).Return(true).Once() + + assert.True(t, Gate()) + + mockGate.AssertExpectations(t) +} +``` + +## Mock facades.Grpc + +```go + +import ( + "context" + "errors" + "testing" + + "github.com/goravel/framework/testing/mock" + "github.com/stretchr/testify/assert" + "google.golang.org/grpc" + + "goravel/app/facades" +) + +func Grpc() (*grpc.ClientConn, error) { + return facades.Grpc().Client(context.Background(), "user") +} + +func TestGrpc(t *testing.T) { + mockFactory := mock.Factory() + mockGrpc := mockFactory.Grpc() + mockGrpc.On("Client", context.Background(), "user").Return(nil, errors.New("error")).Once() + conn, err := Grpc() + + assert.Nil(t, conn) + assert.EqualError(t, err, "error") + + mockGrpc.AssertExpectations(t) +} +``` + +## Mock facades.Hash + +```go +import ( + "errors" + "testing" + + "github.com/goravel/framework/testing/mock" + "github.com/stretchr/testify/assert" + "google.golang.org/grpc" + + "goravel/app/facades" +) + +func Hash() (string, error) { + return facades.Hash().Make("Goravel") +} + +func TestHash(t *testing.T) { + mockFactory := mock.Factory() + mockHash := mockFactory.Hash() + mockHash.On("Make", "Goravel").Return("test", nil).Once() + + res, err := Hash() + assert.Equal(t, "test", res) + assert.Nil(t, err) + + mockHash.AssertExpectations(t) +} +``` + +## Mock facades.Lang + +```go +func Lang() string { + return facades.Lang(context.Background()).Get("name") +} + +func TestLang(t *testing.T) { + mockFactory := mock.Factory() + mockLang := mockFactory.Lang() + mockLang.On("Get", "name").Return("Goravel").Once() + + assert.Equal(t, "Goravel", Lang()) + mockLang.AssertExpectations(t) +} +``` + +## Mock facades.Log + +`facades.Log()` doesn't implement mock, use `fmt` instead of the actual log output, easy to debug during testing. + +```go +import "github.com/goravel/framework/testing/mock" + +func Log() { + facades.Log().Debug("test") +} + +func TestLog(t *testing.T) { + mockFactory := mock.Factory() + mockFactory.Log() + + Log() +} +``` + +## Mock facades.Mail + +```go +import "github.com/goravel/framework/testing/mock" + +func Mail() error { + return facades.Mail().From(mail.From{Address: "example@example.com", Name: "example"}). + To([]string{"example@example.com"}). + Content(mail.Content{Subject: "Subject", Html: "

Hello Goravel

"}). + Send() +} + +func TestMail(t *testing.T) { + mockFactory := mock.Factory() + mockMail := mockFactory.Mail() + mockMail.On("From", mail.From{Address: "example@example.com", Name: "example"}).Return(mockMail) + mockMail.On("To", []string{"example@example.com"}).Return(mockMail) + mockMail.On("Content", mail.Content{Subject: "Subject", Html: "

Hello Goravel

"}).Return(mockMail) + mockMail.On("Send").Return(nil) + + assert.Nil(t, Mail()) + + mockMail.AssertExpectations(t) +} +``` + +## Mock facades.Orm + +```go +import "github.com/goravel/framework/testing/mock" + +func Orm() error { + if err := facades.Orm().Query().Create(&Test{}); err != nil { + return err + } + + var test Test + return facades.Orm().Query().Where("id = ?", 1).Find(&test) +} + +func TestOrm(t *testing.T) { + mockFactory := mock.Factory() + mockOrm := mockFactory.Orm() + mockOrmQuery := mockFactory.OrmQuery() + mockOrm.On("Query").Return(mockOrmQuery) + + mockOrmQuery.On("Create", mock.Anything).Return(nil).Once() + mockOrmQuery.On("Where", "id = ?", 1).Return(mockOrmDB).Once() + mockOrmQuery.On("Find", mock.Anything).Return(nil).Once() + + assert.Nil(t, Orm()) + + mockOrm.AssertExpectations(t) + mockOrmQuery.AssertExpectations(t) +} + +func Transaction() error { + return facades.Orm().Transaction(func(tx contractorm.Transaction) error { + var test Test + if err := tx.Create(&test); err != nil { + return err + } + + var test1 Test + return tx.Where("id = ?", test.ID).Find(&test1) + }) +} + +func TestTransaction(t *testing.T) { + mockFactory := mock.Factory() + mockOrm := mockFactory.Orm() + mockOrmTransaction := mockFactory.OrmTransaction() + mockOrm.On("Transaction", mock.Anything).Return(func(txFunc func(tx orm.Transaction) error) error { + return txFunc(mockOrmTransaction) + }) + + var test Test + mockOrmTransaction.On("Create", &test).Return(func(test2 interface{}) error { + test2.(*Test).ID = 1 + + return nil + }).Once() + mockOrmTransaction.On("Where", "id = ?", uint(1)).Return(mockOrmTransaction).Once() + mockOrmTransaction.On("Find", mock.Anything).Return(nil).Once() + + assert.Nil(t, Transaction()) + + mockOrm.AssertExpectations(t) + mockOrmTransaction.AssertExpectations(t) +} + +func Begin() error { + tx, _ := facades.Orm().Query().Begin() + user := models.User{Name: "Goravel"} + if err := tx.Create(&user); err != nil { + return tx.Rollback() + } else { + return tx.Commit() + } +} +``` + +## Mock facades.Queue + +```go +import "github.com/goravel/framework/testing/mock" + +func Queue() error { + return facades.Queue().Job(&jobs.TestSyncJob{}, []queue.Arg{}).Dispatch() +} + +func TestQueue(t *testing.T) { + mockFactory := mock.Factory() + mockQueue := mockFactory.Queue() + mockTask := mockFactory.QueueTask() + mockQueue.On("Job", mock.Anything, mock.Anything).Return(mockTask).Once() + mockTask.On("Dispatch").Return(nil).Once() + + assert.Nil(t, Queue()) + + mockQueue.AssertExpectations(t) + mockTask.AssertExpectations(t) +} +``` + +## Mock facades.Storage + +```go +import ( + "context" + "testing" + + "github.com/goravel/framework/filesystem" + "github.com/goravel/framework/testing/mock" + + "goravel/app/facades" +) + +func Storage() (string, error) { + file, _ := filesystem.NewFile("1.txt") + + return facades.Storage().WithContext(context.Background()).PutFile("file", file) +} + +func TestStorage(t *testing.T) { + mockFactory := mock.Factory() + mockStorage := mockFactory.Storage() + mockDriver := mockFactory.StorageDriver() + mockStorage.On("WithContext", context.Background()).Return(mockDriver).Once() + file, _ := filesystem.NewFile("1.txt") + mockDriver.On("PutFile", "file", file).Return("", nil).Once() + path, err := Storage() + + assert.Equal(t, "", path) + assert.Nil(t, err) + + mockStorage.AssertExpectations(t) + mockDriver.AssertExpectations(t) +} + +``` + +## Mock facades.Validation + +```go +import ( + "testing" + + "github.com/goravel/framework/testing/mock" + "github.com/stretchr/testify/assert" + + "goravel/app/facades" +) + +func Validation() string { + validator, _ := facades.Validation().Make(map[string]string{ + "a": "b", + }, map[string]string{ + "a": "required", + }) + errors := validator.Errors() + + return errors.One("a") +} + +func TestValidation(t *testing.T) { + mockFactory := mock.Factory() + mockValidation := mockFactory.Validation() + mockValidator := mockFactory.ValidationValidator() + mockErrors := mockFactory.ValidationErrors() + mockValidation.On("Make", map[string]string{ + "a": "b", + }, map[string]string{ + "a": "required", + }).Return(mockValidator, nil).Once() + mockValidator.On("Errors").Return(mockErrors).Once() + mockErrors.On("One", "a").Return("error").Once() + err := Validation() + + assert.Equal(t, "error", err) + + mockValidation.AssertExpectations(t) + mockValidator.AssertExpectations(t) + mockErrors.AssertExpectations(t) +} +``` + +## Mock facades.View + +```go +import ( + "testing" + + "github.com/goravel/framework/testing/mock" + "github.com/stretchr/testify/assert" + + "goravel/app/facades" +) + +func View() bool { + return facades.View().Exists("welcome.tmpl") +} + +func TestView(t *testing.T) { + mockFactory := mock.Factory() + mockView := mockFactory.View() + mockView.On("Exists", "welcome.tmpl").Return(true).Once() + + assert.True(t, View()) + + mockView.AssertExpectations(t) +} +``` From 6dc91514cb542bdec67e0d7e937a16f976b53c15 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:41 +0800 Subject: [PATCH 041/163] New translations controllers.md (Uzbek) [skip ci] Update translations (Uzbek) controllers.md --- uz_UZ/the-basics/controllers.md | 84 +++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 uz_UZ/the-basics/controllers.md diff --git a/uz_UZ/the-basics/controllers.md b/uz_UZ/the-basics/controllers.md new file mode 100644 index 000000000..5d6a99859 --- /dev/null +++ b/uz_UZ/the-basics/controllers.md @@ -0,0 +1,84 @@ +# Controllers + +[[toc]] + +## Introduction + +Instead of defining all request processing logic in the form of a closure in a separate route, a controller can be used for integration. The controllers are stored in the `app/http/controllers` directory. + +## Define Controllers + +The following is an example of a basic controller: + +```go +package controllers + +import ( + "github.com/goravel/framework/contracts/http" + + "goravel/app/facades" +) + +type UserController struct { + // Dependent services +} + +func NewUserController() *UserController { + return &UserController{ + // Inject services + } +} + +func (r *UserController) Show(ctx http.Context) http.Response { + return ctx.Response().Success().Json(http.Json{ + "Hello": "Goravel", + }) +} +``` + +The route define: + +```go +package routes + +import ( + "goravel/app/facades" + "goravel/app/http/controllers" +) + +func Api() { + userController := controllers.NewUserController() + facades.Route().Get("/{id}", userController.Show) +} +``` + +### Create Controller + +```shell +./artisan make:controller UserController +./artisan make:controller user/UserController +``` + +## Resource Controllers + +If you think of each Eloquent model in your application as a "resource", it is typical to perform the same sets of actions against each resource in your application. For example, imagine your application contains a `Photo` model and a `Movie` model. It is likely that users can create, read, update, or delete these resources. + +Because of this common use case, Goravel resource routing assigns the typical create, read, update, and delete ("CRUD") routes to a controller with a single line of code. To get started, we can use the `make:controller` Artisan command's `--resource` option to quickly create a controller to handle these actions: + +```shell +./artisan make:controller --resource PhotoController +``` + +This command will generate a controller at `app/http/controllers/photo_controller.go`. The controller will contain a method for each of the available resource operations. Next, you may register a resource route that points to the controller: + +```go +facades.Route().Resource("photos", controllers.NewPhotoController()) +``` + +| Verb | URI | Action | +| --------- | ----------------- | ------- | +| GET | `/photos` | Index | +| POST | `/photos` | Store | +| GET | `/photos/{photo}` | Show | +| PUT/PATCH | `/photos/{photo}` | Update | +| DELETE | `/photos/{photo}` | Destroy | From 353b1ffaf46986e97b275b05b59bf1fbc26fa7d2 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:42 +0800 Subject: [PATCH 042/163] New translations grpc.md (Uzbek) [skip ci] Update translations (Uzbek) grpc.md --- uz_UZ/the-basics/grpc.md | 388 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 388 insertions(+) create mode 100644 uz_UZ/the-basics/grpc.md diff --git a/uz_UZ/the-basics/grpc.md b/uz_UZ/the-basics/grpc.md new file mode 100644 index 000000000..a7f996cee --- /dev/null +++ b/uz_UZ/the-basics/grpc.md @@ -0,0 +1,388 @@ +# Grpc + +[[toc]] + +## Introduction + +Grpc module can be operated by `facades.Grpc()`. Goravel provides an elegant way to build and consume gRPC services, supporting both server and client sides. + +## Configuration + +In the `config/grpc.go` file, you can configure the Grpc module, where `grpc.host` configures the domain name of the server, and `grpc.servers` configures the servers which the client will connect to. + +## Controllers + +Controllers can be defined in the `app/grpc/controllers` directory. + +```go +// app/grpc/controllers/user_controller.go +package controllers + +import ( + "context" + "net/http" + + proto "github.com/goravel/example-proto" +) + +type UserController struct {} + +func NewUserController() *UserController { + return &UserController{} +} + +func (r *UserController) GetUser(ctx context.Context, req *proto.UserRequest) (*proto.UserResponse, error) { + return &proto.UserResponse{ + Code: http.StatusOK, + Data: &proto.User{ + Id: 1, + Name: "Goravel", + Token: req.GetToken(), + }, + }, nil +} +``` + +## Define routing + +All routing files can be defined in the `routes` directory, such as `routes/grpc.go`. + +```go +// routes/grpc.go +package routes + +import ( + proto "github.com/goravel/example-proto" + + "goravel/app/facades" + "goravel/app/grpc/controllers" +) + +func Grpc() { + proto.RegisterUserServiceServer(facades.Grpc().Server(), controllers.NewUserController()) +} +``` + +### Register routing + +Register routing in the `bootstrap/app.go::WithRouting` function after routing was defined. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithRouting(func() { + routes.Grpc() + }). + WithConfig(config.Boot). + Create() +} +``` + +## Interceptor + +Interceptors provide a way to intercept and modify gRPC requests and responses. They can be used for logging, authentication, metrics, and more. + +### Define Interceptors + +Interceptors can be defined in the `app/grpc/interceptors` folder. + +**Server Interceptor Example:** + +```go +// app/grpc/interceptors/test_server.go +package interceptors + +import ( + "context" + + "google.golang.org/grpc" +) + +func TestServer(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) { + // Add your logic before the request is handled + // For example: logging, authentication, etc. + + return handler(ctx, req) +} +``` + +**Client Interceptor Example:** + +```go +// app/grpc/interceptors/test_client.go +package interceptors + +import ( + "context" + + "google.golang.org/grpc" +) + +func TestClient(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { + // Add your logic before the request is sent + // For example: logging, adding metadata, etc. + + return invoker(ctx, method, req, reply, cc, opts...) +} +``` + +### Register Interceptors + +Register interceptors in the `bootstrap/app.go` file using the `WithGrpcServerInterceptors`, `WithGrpcClientInterceptors`, `WithGrpcServerStatsHandlers`, and `WithGrpcClientStatsHandlers` functions. + +```go +import ( + "github.com/goravel/framework/contracts/foundation" + "google.golang.org/grpc" + "google.golang.org/grpc/stats" + + "goravel/app/grpc/interceptors" +) + +func Boot() foundation.Application { + return foundation.Setup(). + WithGrpcServerInterceptors(func() []grpc.UnaryServerInterceptor { + return []grpc.UnaryServerInterceptor{ + interceptors.TestServer, + } + }). + WithGrpcClientInterceptors(func() map[string][]grpc.UnaryClientInterceptor { + return map[string][]grpc.UnaryClientInterceptor{ + "default": { + interceptors.TestClient, + }, + } + }). + WithGrpcServerStatsHandlers(func() []stats.Handler { + return []stats.Handler{} + }). + WithGrpcClientStatsHandlers(func() map[string][]stats.Handler { + return map[string][]stats.Handler{} + }). + Create() +} +``` + +### Apply Interceptors to Servers + +The `default` in the example above is a group name that can be applied to the configuration item `grpc.servers.interceptors`. In this way, the client will be applied to all interceptors under the group. + +```go +package config + +import ( + "goravel/app/facades" +) + +func init() { + config := facades.Config() + config.Add("grpc", map[string]any{ + "host": config.Env("GRPC_HOST", ""), + "port": config.Env("GRPC_PORT", ""), + + "servers": map[string]any{ + "user": map[string]any{ + "host": config.Env("GRPC_USER_HOST", ""), + "port": config.Env("GRPC_USER_PORT", ""), + "interceptors": []string{"default"}, + "stats_handlers": []string{}, + }, + }, + }) +} +``` + +## Stats Handlers + +Stats handlers are gRPC's mechanism for collecting metrics and monitoring RPC calls. They provide hooks into the lifecycle of both client and server RPCs, making them ideal for: + +- Request/response monitoring +- Performance metrics collection +- Custom observability integrations +- Logging and debugging + +### Register Stats Handlers + +Stats handlers can be registered in the `bootstrap/app.go` file using the `WithGrpcServerStatsHandlers` and `WithGrpcClientStatsHandlers` functions. + +**Server Stats Handler Example:** + +```go +// app/grpc/stats/server_handler.go +package stats + +import ( + "context" + + "google.golang.org/grpc/stats" +) + +type ServerStatsHandler struct{} + +func NewServerStatsHandler() stats.Handler { + return &ServerStatsHandler{} +} + +func (h *ServerStatsHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context { + // Called at the beginning of each RPC + return ctx +} + +func (h *ServerStatsHandler) HandleRPC(ctx context.Context, s stats.RPCStats) { + // Called for each RPC event +} + +func (h *ServerStatsHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context { + // Called when a connection is established + return ctx +} + +func (h *ServerStatsHandler) HandleConn(ctx context.Context, s stats.ConnStats) { + // Called for connection events +} +``` + +**Client Stats Handler Example:** + +```go +// app/grpc/stats/client_handler.go +package stats + +import ( + "context" + + "google.golang.org/grpc/stats" +) + +type ClientStatsHandler struct{} + +func NewClientStatsHandler() stats.Handler { + return &ClientStatsHandler{} +} + +func (h *ClientStatsHandler) TagRPC(ctx context.Context, info *stats.RPCTagInfo) context.Context { + return ctx +} + +func (h *ClientStatsHandler) HandleRPC(ctx context.Context, s stats.RPCStats) { + // Handle RPC events like Begin, End, InPayload, OutPayload +} + +func (h *ClientStatsHandler) TagConn(ctx context.Context, info *stats.ConnTagInfo) context.Context { + return ctx +} + +func (h *ClientStatsHandler) HandleConn(ctx context.Context, s stats.ConnStats) { + // Handle connection events +} +``` + +### Register in Bootstrap + +Register your stats handlers in `bootstrap/app.go`: + +```go +import ( + "google.golang.org/grpc/stats" + + grpcstats "goravel/app/grpc/stats" +) + +func Boot() foundation.Application { + return foundation.Setup(). + WithGrpcServerStatsHandlers(func() []stats.Handler { + return []stats.Handler{ + grpcstats.NewServerStatsHandler(), + } + }). + WithGrpcClientStatsHandlers(func() map[string][]stats.Handler { + return map[string][]stats.Handler{ + "user": { + grpcstats.NewClientStatsHandler(), + }, + } + }). + Create() +} +``` + +### Apply Stats Handlers to Clients + +The group name (e.g., `"user"`) must be referenced in your `config/grpc.go` file under the client's `stats_handlers` array: + +```go +package config + +import ( + "goravel/app/facades" +) + +func init() { + config := facades.Config() + config.Add("grpc", map[string]any{ + "host": config.Env("GRPC_HOST", ""), + "port": config.Env("GRPC_PORT", ""), + + "servers": map[string]any{ + "user": map[string]any{ + "host": config.Env("GRPC_USER_HOST", ""), + "port": config.Env("GRPC_USER_PORT", ""), + "interceptors": []string{"default"}, + "stats_handlers": []string{"user"}, // Apply "user" stats handler group + }, + }, + }) +} +``` + +## gRPC Client + +Goravel provides an easy way to create gRPC clients to consume gRPC services. + +### Connect to gRPC Server + +You can connect to a gRPC server using the `facades.Grpc().Connect()` method. The connection name should match the key defined in `config/grpc.go`. + +```go +// app/http/controllers/grpc_controller.go +package controllers + +import ( + "fmt" + + proto "github.com/goravel/example-proto" + "github.com/goravel/framework/contracts/http" + + "goravel/app/facades" +) + +type GrpcController struct { + userService proto.UserServiceClient +} + +func NewGrpcController() *GrpcController { + // The initialization process can be moved to app/services/*.go + client, err := facades.Grpc().Connect("user") + if err != nil { + facades.Log().Error(fmt.Sprintf("failed to connect to user server: %+v", err)) + } + + return &GrpcController{ + userService: proto.NewUserServiceClient(client), + } +} + +func (r *GrpcController) User(ctx http.Context) http.Response { + resp, err := r.userService.GetUser(ctx, &proto.UserRequest{ + Token: ctx.Request().Input("token"), + }) + if err != nil { + return ctx.Response().String(http.StatusInternalServerError, fmt.Sprintf("call UserService.GetUser err: %+v", err)) + } + if resp.Code != http.StatusOK { + return ctx.Response().String(http.StatusInternalServerError, fmt.Sprintf("user service returns error, code: %d, message: %s", resp.Code, resp.Message)) + } + + return ctx.Response().Success().Json(resp.GetData()) +} +``` From 3b06ddc83b9c7f4f7f78803c3ab41acbd7b47d93 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:43 +0800 Subject: [PATCH 043/163] New translations logging.md (Uzbek) [skip ci] Update translations (Uzbek) logging.md --- uz_UZ/the-basics/logging.md | 114 ++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 uz_UZ/the-basics/logging.md diff --git a/uz_UZ/the-basics/logging.md b/uz_UZ/the-basics/logging.md new file mode 100644 index 000000000..5aeb28f00 --- /dev/null +++ b/uz_UZ/the-basics/logging.md @@ -0,0 +1,114 @@ +# Logging + +[[toc]] + +## Introduction + +In order to understand the running status of the application, Goravel provides a powerful log service that can record log messages and system errors to a file or other channels through `facades.Log()`. + +## Configuration + +To configure various log channels, custom configurations can be made in `config/logging.go`. + +`Goravel` uses `stack` channel to record logs by default, `stack` allows logs to be forwarded to multiple channels. + +The `print` configuration in `single` and `daily` drivers can control log output to the console. + +## Available channel drivers + +| Name | Description | +| -------- | ----------------------- | +| `stack` | Allow multiple channels | +| `single` | Single log file | +| `daily` | One log file per day | +| `custom` | Custom drive | + +### Inject Context + +```go +facades.Log().WithContext(ctx) +``` + +## Write log messages + +```go +facades.Log().Debug(message) +facades.Log().Debugf(message, args) +facades.Log().Info(message) +facades.Log().Infof(message, args) +facades.Log().Warning(message) +facades.Log().Warningf(message, args) +facades.Log().Error(message) +facades.Log().Errorf(message, args) +facades.Log().Fatal(message) +facades.Log().Fatalf(message, args) +facades.Log().Panic(message) +facades.Log().Panicf(message, args) +``` + +### Write to a specific channel + +Sometimes, you may want to record messages to a channel other than the application's default channel: + +```go +facades.Log().Channel("single").Info(message) +``` + +If you want to write to multiple channels at the same time, you can use the `Stack` method: + +```go +facades.Log().Stack([]string{"single", "slack"}).Info(message) +``` + +## Chain Methods + +Goravel provides convenient chain methods, that make it easy to insert more useful information into the log: + +```go +facades.Log().User("John").Debug(message) +``` + +| Method | Action | +| --------- | -------------------------------------------------------------------------------------- | +| Code | Set a code or slug that describes the log. | +| Hint | Set a hint for faster debugging. | +| In | Set the feature category or domain in which the log entry is relevant. | +| Owner | Useful for alerting purposes. | +| Request | Supplies a http.Request. | +| Response | Supplies a http.Response. | +| Tags | Add multiple tags, describing the feature returning an error. | +| User | Set the user associated with the log entry. | +| With | Add key-value pairs to the context of the log entry. | +| WithTrace | Add stack information to the log entry. | + +## Create a custom channel + +If you want to define a completely custom channel, you can specify the `custom` driver type in the `config/logging.go` configuration file. +Then include a `via` option to implement a `framework\contracts\log\Logger` structure: + +```go +// config/logging.go +"custom": map[string]interface{}{ + "driver": "custom", + "via": &CustomLogger{}, +}, +``` + +### Implement Driver + +Implement `framework\contracts\log\Logger` interface. + +```go +// framework/contracts/log/Logger +package log + +type Logger interface { + // Handle pass channel config path here + Handle(channel string) (Handler, error) +} +``` + +You can check the daily and single log drivers for reference: + +- [Daily](https://github.com/goravel/framework/blob/master/log/logger/daily.go) +- [Single](https://github.com/goravel/framework/blob/master/log/logger/single.go) From 4fed31cd924f93a4f39b0a7d7ba843a33a22ca38 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:44 +0800 Subject: [PATCH 044/163] New translations middleware.md (Uzbek) [skip ci] Update translations (Uzbek) middleware.md --- uz_UZ/the-basics/middleware.md | 82 ++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 uz_UZ/the-basics/middleware.md diff --git a/uz_UZ/the-basics/middleware.md b/uz_UZ/the-basics/middleware.md new file mode 100644 index 000000000..beed2adbb --- /dev/null +++ b/uz_UZ/the-basics/middleware.md @@ -0,0 +1,82 @@ +# Middleware + +[[toc]] + +## Introduction + +Middleware provide a convenient mechanism for inspecting and filtering HTTP requests entering your application. + +## Define Middleware + +You can create your own middleware in the `app/http/middleware` directory, the structure is as follows. + +```go +package middleware + +import ( + "github.com/goravel/framework/contracts/http" +) + +func Auth() http.Middleware { + return func(ctx http.Context) { + ctx.Request().Next() + } +} +``` + +### Create Middleware By Command + +``` +./artisan make:middleware Auth + +// Support nested folders +./artisan make:middleware user/Auth +``` + +## Register Middleware + +### Global Middleware + +If you want to apply middleware for every HTTP request of your application, you only need to register the middleware in the `WithMiddleware` function in the `bootstrap/app.go` file. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithMiddleware(func(handler configuration.Middleware) { + handler.Append( + middleware.Custom(), + ) + }). + WithConfig(config.Boot). + Create() +} +``` + +The `handler` provides multiple functions to manage middleware: + +- `Append(middlewares ...http.Middleware)`: Append middleware to the end of the middleware stack. +- `GetGlobalMiddleware() []http.Middleware`: Get all global middleware. +- `GetRecover() func(ctx http.Context, err any)`: Get the custom recovery function. +- `Prepend(middlewares ...http.Middleware)`: Prepend middleware to the beginning of the middleware stack. +- `Recover(fn func(ctx http.Context, err any)) Middleware`: Set a custom recovery function to handle panics. +- `Use(middleware ...http.Middleware) Middleware`: Replace the current middleware stack with the given middleware. + +### Assign Middleware for Routing + +You can register the middleware for some routing separately: + +```go +import "github.com/goravel/framework/http/middleware" + +facades.Route().Middleware(middleware.Auth()).Get("users", userController.Show) +``` + +## Abort Request + +In middleware, if you need to interrupt the request, you can use the `Abort` method. + +```go +ctx.Request().Abort() +ctx.Request().Abort(http.StatusNotFound) +ctx.Response().String(http.StatusNotFound, "Not Found").Abort() +``` From 2d944088fdd18ddfa9eb7a9eb6e681af210af136 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:45 +0800 Subject: [PATCH 045/163] New translations request.md (Uzbek) [skip ci] Update translations (Uzbek) request.md --- uz_UZ/the-basics/request.md | 231 ++++++++++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 uz_UZ/the-basics/request.md diff --git a/uz_UZ/the-basics/request.md b/uz_UZ/the-basics/request.md new file mode 100644 index 000000000..c638037c1 --- /dev/null +++ b/uz_UZ/the-basics/request.md @@ -0,0 +1,231 @@ +# HTTP Requests + +[[toc]] + +## Introduction + +The `contracts/http/Request` method of Goravel can interact with the current HTTP request processed by the application, and get the input and files submitted together. + +## Interacting With The Request + +The `http.Context` instance is automatically injected into the controller: + +```go +import "github.com/goravel/framework/contracts/http" + +facades.Route().Get("/", func(ctx http.Context) http.Response {}) +``` + +### Retrieving The Request Path + +```go +path := ctx.Request().Path() // /users/1 + +originPath := ctx.Request().OriginPath() // /users/{id} +``` + +### Retrieving The Request URL + +```go +url := ctx.Request().Url() // /users?name=Goravel +``` + +### Retrieving The Request HOST + +```go +url := ctx.Request().Host() +``` + +### Retrieving The Full Request URL + +```go +url := ctx.Request().FullUrl() // http://**/users?name=Goravel +``` + +### Retrieving The Request Method + +```go +method := ctx.Request().Method() +``` + +### Retrieving The Request Route Information + +```go +info := ctx.Request().Info() +``` + +### Retrieving The Request Route Name + +```go +name := ctx.Request().Name() +``` + +### Request Headers + +```go +header := ctx.Request().Header("X-Header-Name", "default") +headers := ctx.Request().Headers() +``` + +### Request IP Address + +```go +ip := ctx.Request().Ip() +``` + +## Input + +### Retrieving All Input Data + +You may retrieve all of the incoming request's input data as `map[string]any` using the `All` method, which is a collection of `json`, `form` and `query`(priority from front to back). + +```go +data := ctx.Request().All() +``` + +### Retrieving a Route Value + +```go +// /users/{id} +id := ctx.Request().Route("id") +id := ctx.Request().RouteInt("id") +id := ctx.Request().RouteInt64("id") +``` + +### Retrieving Input From The Query String + +```go +// /users?name=goravel +name := ctx.Request().Query("name") +name := ctx.Request().Query("name", "default") + +// /users?id=1 +name := ctx.Request().QueryInt("id") +name := ctx.Request().QueryInt64("id") +name := ctx.Request().QueryBool("id") + +// /users?names=goravel1&names=goravel2 +names := ctx.Request().QueryArray("names") + +// /users?names[a]=goravel1&names[b]=goravel2 +names := ctx.Request().QueryMap("names") + +queries := ctx.Request().Queries() +``` + +> Note: Only one-dimensional Json data can be obtained, otherwise it will return empty. + +### Retrieving An Input Value + +Access all of the user input without worrying about which HTTP verb was used for the request. Retrieve order: `json`, `form`. + +```go +name := ctx.Request().Input("name") +name := ctx.Request().Input("name", "goravel") +name := ctx.Request().InputInt("name") +name := ctx.Request().InputInt64("name") +name := ctx.Request().InputBool("name") +name := ctx.Request().InputArray("name") +name := ctx.Request().InputMap("name") +name := ctx.Request().InputMapArray("name") +``` + +### Bind Json/Form + +```go +type User struct { + Name string `form:"code" json:"code"` +} + +var user User +err := ctx.Request().Bind(&user) +``` + +```go +var user map[string]any +err := ctx.Request().Bind(&user) +``` + +### Bind Query + +Only support bind Query to struct: + +```go +type Test struct { + ID string `form:"id"` +} +var test Test +err := ctx.Request().BindQuery(&test) +``` + +## Cookie + +### Retrieving a Cookie Value + +Goravel provides a simple way to work with `cookie`. Use the `Cookie` method on the `Request` instance to retrieve a `cookie` value, will return an empty string if the `cookie` is not present. You can also define a default value in the second argument. + +```go +value := ctx.Request().Cookie("name") +value := ctx.Request().Cookie("name", "default") +``` + +## File + +### Retrieving File + +```go +file, err := ctx.Request().File("file") +files, err := ctx.Request().Files("file") +``` + +### Save File + +```go +file, err := ctx.Request().File("file") +file.Store("./public") +``` + +### Get Origin Request + +```go +request := ctx.Request().Origin() +``` + +### Attach Data + +```go +ctx.WithValue("user", "Goravel") +``` + +### Get Data + +```go +user := ctx.Value("user") +``` + +### Get Context + +```go +ctx := ctx.Context() +``` + +## Custom Recovery + +You can set a custom `recovery` in the `bootstrap/app.go::WithMiddleware` function. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithMiddleware(func(handler configuration.Middleware) { + handler.Append( + httpmiddleware.Throttle("global"), + sessionmiddleware.StartSession(), + ).Recover(func(ctx http.Context, err any) { + facades.Log().Error(err) + _ = ctx.Response().String(contractshttp.StatusInternalServerError, "recover").Abort() + }) + }). + WithConfig(config.Boot). + Create() +} +``` From a7baa7ee8438edbf88041ad7f1fa82bcd671af05 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:46 +0800 Subject: [PATCH 046/163] New translations response.md (Uzbek) [skip ci] Update translations (Uzbek) response.md --- uz_UZ/the-basics/response.md | 164 +++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 uz_UZ/the-basics/response.md diff --git a/uz_UZ/the-basics/response.md b/uz_UZ/the-basics/response.md new file mode 100644 index 000000000..0987f6cb7 --- /dev/null +++ b/uz_UZ/the-basics/response.md @@ -0,0 +1,164 @@ +# HTTP Response + +[[toc]] + +## Introduction + +You can use `ctx.Response()` for HTTP response in the Controller. + +## String + +```go +import "github.com/goravel/framework/contracts/http" + +ctx.Response().String(http.StatusOK, "Hello Goravel") +``` + +## JSON + +```go +import ( + "github.com/goravel/framework/contracts/http" +) + +ctx.Response().Json(http.StatusOK, http.Json{ + "Hello": "Goravel", +}) + +ctx.Response().Json(http.StatusOK, struct { + ID uint `json:"id"` + Name string `json:"name"` +}{ + Id: 1, + Front: "Goravel", +}) +``` + +## Custom Return + +```go +ctx.Response().Data(http.StatusOK, "text/html; charset=utf-8", []byte("Goravel")) +``` + +## Response File + +```go +import "net/http" + +ctx.Response().File("./public/logo.png") +``` + +## Download File + +```go +import "net/http" + +ctx.Response().Download("./public/logo.png", "1.png") +``` + +## Attach Header + +```go +import "github.com/goravel/framework/contracts/http" + +ctx.Response().Header("Content", "Goravel").String(http.StatusOK, "Hello Goravel") +``` + +## Cookie + +### Set Cookie + +Use the `Cookie` method on the `response` instance to set a `cookie`. The `Cookie` method accepts a `http.Cookie` instance, which allows you to set various cookie options. + +```go +import ( + "time" + "github.com/goravel/framework/contracts/http" +) + +ctx.Response().Cookie(http.Cookie{ + Name: "name", + Value: "Goravel", + Path: "/", + Domain: "goravel.dev", + Expires: time.Now().Add(24 * time.Hour), + Secure: true, + HttpOnly: true, +}) +``` + +### Expire Cookie + +Use the `WithoutCookie` method to remove a cookie. + +```go +ctx.Response().WithoutCookie("name") +``` + +## Return Success + +```go +ctx.Response().Success().String("Hello Goravel") +ctx.Response().Success().Json(http.Json{ + "Hello": "Goravel", +}) +``` + +## Custom Code + +```go +ctx.Response().Status(http.StatusOK).Json(http.Json{ + "hello": "Goravel", +}) +``` + +## Return Stream + +```go +ctx.Response().Stream(http.StatusCreated, func(w http.StreamWriter) error { + data := []string{"a", "b", "c"} + for _, item := range data { + if _, err := w.Write([]byte(item + "\n")); err != nil { + return err + } + + if err := w.Flush(); err != nil { + return err + } + + time.Sleep(1 * time.Second) + } + + return nil +}) +``` + +## Redirect + +```go +ctx.Response().Redirect(http.StatusMovedPermanently, "https://goravel.dev") +``` + +## No Content + +```go +ctx.Response().NoContent() +ctx.Response().NoContent(http.StatusOk) +``` + +## Get Response + +You can obtain all the information from `ctx.Response()`, which is commonly used in HTTP middleware: + +```go +origin := ctx.Response().Origin() +``` + +`origin` contains some methods as shown below: + +| Method | Action | +| ------ | ------------------- | +| Body | Get response data | +| Header | Get response header | +| Size | Get response size | +| Status | Get response status | From f597147d795961e43a05b7ee7db8192a299862c9 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:47 +0800 Subject: [PATCH 047/163] New translations routing.md (Uzbek) [skip ci] Update translations (Uzbek) routing.md --- uz_UZ/the-basics/routing.md | 283 ++++++++++++++++++++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 uz_UZ/the-basics/routing.md diff --git a/uz_UZ/the-basics/routing.md b/uz_UZ/the-basics/routing.md new file mode 100644 index 000000000..35783955c --- /dev/null +++ b/uz_UZ/the-basics/routing.md @@ -0,0 +1,283 @@ +# Routing + +[[toc]] + +## Introduction + +The Goravel routing module can be operated by `facades.Route()`. + +## HTTP Driver + +Goravel uses [gin](https://github.com/gin-gonic/gin) as its default HTTP driver. To use other drivers, configure them in the `config/http.go` file. The official default supports [gin](https://github.com/gin-gonic/gin) and [fiber](https://github.com/gofiber/fiber). + +| Driver | Link | +| ------ | ---------------------------------------------------------------------------------------------------- | +| Gin | [https://github.com/goravel/gin](https://github.com/goravel/gin) | +| Fiber | [https://github.com/goravel/fiber](https://github.com/goravel/fiber) | + +## Default Routing File + +To define routing files, simply navigate to the `routes` directory. By default, the framework utilizes a sample route located in `routes/web.go` and it is registered in the `bootstrap/app.go::WithRouting` function. + +If you require more precise management, you can add routing files to the `routes` directory and register them in the `bootstrap/app.go::WithRouting` function as well. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithRouting(func() { + routes.Web() + }). + WithConfig(config.Boot). + Create() +} +``` + +## Get Routes List + +Use the `route:list` command to view routes list: + +```shell +./artisan route:list +``` + +### Routing Methods + +| Methods | Action | +| ---------- | ------------------------------------- | +| Group | [Group Routing](#group-routing) | +| Prefix | [Routing Prefix](#routing-prefix) | +| ServeHTTP | [Testing Routing](#testing-routing) | +| Get | [Basic Routing](#basic-routing) | +| Post | [Basic Routing](#basic-routing) | +| Put | [Basic Routing](#basic-routing) | +| Delete | [Basic Routing](#basic-routing) | +| Patch | [Basic Routing](#basic-routing) | +| Options | [Basic Routing](#basic-routing) | +| Any | [Basic Routing](#basic-routing) | +| Resource | [Resource Routing](#resource-routing) | +| Static | [File Routing](#file-routing) | +| StaticFile | [File Routing](#file-routing) | +| StaticFS | [File Routing](#file-routing) | +| Middleware | [Middleware](#middleware) | +| GetRoutes | [Get All Routes](#get-all-routes) | +| Name | [Set Route Name](#set-route-name) | +| Info | [Get Route Info](#get-route-info) | + +## Basic Routing + +```go +facades.Route().Get("/", func(ctx http.Context) http.Response { + return ctx.Response().Json(http.StatusOK, http.Json{ + "Hello": "Goravel", + }) +}) +facades.Route().Post("/", userController.Show) +facades.Route().Put("/", userController.Show) +facades.Route().Delete("/", userController.Show) +facades.Route().Patch("/", userController.Show) +facades.Route().Options("/", userController.Show) +facades.Route().Any("/", userController.Show) +``` + +## Resource Routing + +```go +import "github.com/goravel/framework/contracts/http" + +resourceController := NewResourceController() +facades.Route().Resource("/resource", resourceController) + +type ResourceController struct{} +func NewResourceController () *ResourceController { + return &ResourceController{} +} +// GET /resource +func (c *ResourceController) Index(ctx http.Context) {} +// GET /resource/{id} +func (c *ResourceController) Show(ctx http.Context) {} +// POST /resource +func (c *ResourceController) Store(ctx http.Context) {} +// PUT /resource/{id} +func (c *ResourceController) Update(ctx http.Context) {} +// DELETE /resource/{id} +func (c *ResourceController) Destroy(ctx http.Context) {} +``` + +## Group Routing + +```go +facades.Route().Group(func(router route.Router) { + router.Get("group/{id}", func(ctx http.Context) http.Response { + return ctx.Response().Success().String(ctx.Request().Query("id", "1")) + }) +}) +``` + +## Routing Prefix + +```go +facades.Route().Prefix("users").Get("/", userController.Show) +``` + +## File Routing + +```go +import "net/http" + +facades.Route().Static("static", "./public") +facades.Route().StaticFile("static-file", "./public/logo.png") +facades.Route().StaticFS("static-fs", http.Dir("./public")) +``` + +## Routing Parameters + +```go +facades.Route().Get("/input/{id}", func(ctx http.Context) http.Response { + return ctx.Response().Success().Json(http.Json{ + "id": ctx.Request().Input("id"), + }) +}) +``` + +Detail [Request](./request.md) + +## Middleware + +```go +import "github.com/goravel/framework/http/middleware" + +facades.Route().Middleware(middleware.Cors()).Get("users", userController.Show) +``` + +Detail [Middleware](./middleware.md) + +## Get All Routes + +```go +routes := facades.Route().GetRoutes() +``` + +## Set Route Name + +```go +facades.Route().Get("users", userController.Index).Name("users.index") +``` + +## Get Route Info + +```go +route := facades.Route().Info("users.index") +``` + +## Fallback Routes + +Using the `Fallback` method, you may define a route that will be executed when no other route matches the incoming request. + +```go +facades.Route().Fallback(func(ctx http.Context) http.Response { + return ctx.Response().String(404, "not found") +}) +``` + +## Rate Limiting + +### Defining Rate Limiters + +Goravel includes powerful and customizable rate-limiting services that you may utilize to restrict the amount of traffic for a given route or group of routes. To get started, you should define rate limiter configurations that meet your application's needs, then register them in the `bootstrap/app.go::WithCallback` function. + +Rate limiters are defined using the `facades.RateLimiter()`'s `For` method. The `For` method accepts a rate limiter name and a closure that returns the limit configuration that should apply to routes that are assigned to the rate limiter. The rate limiter name may be any string you wish: + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithConfig(config.Boot). + WithCallback(func() { + facades.RateLimiter().For("global", func(ctx contractshttp.Context) contractshttp.Limit { + return limit.PerMinute(1000) + }) + }). + Create() +} +``` + +If the incoming request exceeds the specified rate limit, a response with a 429 HTTP status code will automatically be returned by Goravel. If you would like to define your own response that should be returned by a rate limit, you may use the response method: + +```go +facades.RateLimiter().For("global", func(ctx http.Context) http.Limit { + return limit.PerMinute(1000).Response(func(ctx http.Context) { + ctx.Request().AbortWithStatus(http.StatusTooManyRequests) + }) +}) +``` + +Since rate limiter callbacks receive the incoming HTTP request instance, you may build the appropriate rate limit dynamically based on the incoming request or authenticated user: + +```go +facades.RateLimiter().For("global", func(ctx contractshttp.Context) contractshttp.Limit { + // Suppose + if is_vip() { + return limit.PerMinute(100) + } + + return nil +}) +``` + +#### Segmenting Rate Limits + +Sometimes you may wish to segment rate limits by some arbitrary value. For example, you may wish to allow users to access a given route 100 times per minute per IP address. To accomplish this, you may use the `By` method when building your rate limit: + +```go +facades.RateLimiter().For("global", func(ctx contractshttp.Context) contractshttp.Limit { + if is_vip() { + return limit.PerMinute(100).By(ctx.Request().Ip()) + } + + return nil +}) +``` + +To illustrate this feature using another example, we can limit access to the route to 100 times per minute per authenticated user ID or 10 times per minute per IP address for guests: + +```go +facades.RateLimiter().For("global", func(ctx contractshttp.Context) contractshttp.Limit { + if userID != 0 { + return limit.PerMinute(100).By(userID) + } + + return limit.PerMinute(10).By(ctx.Request().Ip()) +}) +``` + +#### Multiple Rate Limits + +If needed, you may return an array of rate limits for a given rate limiter configuration. Each rate limit will be evaluated for the route based on the order they are placed within the array: + +```go +facades.RateLimiter().ForWithLimits("login", func(ctx contractshttp.Context) []contractshttp.Limit { + return []contractshttp.Limit{ + limit.PerMinute(500), + limit.PerMinute(100).By(ctx.Request().Ip()), + } +}) +``` + +### Attaching Rate Limiters To Routes + +Rate limiters may be attached to routes or route groups using the throttle middleware. The throttle middleware accepts the name of the rate limiter you wish to assign to the route: + +```go +import github.com/goravel/framework/http/middleware + +facades.Route().Middleware(middleware.Throttle("global")).Get("/", func(ctx http.Context) http.Response { + return ctx.Response().Json(200, http.Json{ + "Hello": "Goravel", + }) +}) +``` + +## Cross-Origin Resource Sharing (CORS) + +Goravel has CORS enabled by default, the configuration can be modified in `config/cors.go`. + +> For more information on CORS and CORS headers, please consult the [MDN web documentation on CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#The_HTTP_response_headers). From 545abc17d2beca367956ea8e5d3a19f9dcb96aa1 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:48 +0800 Subject: [PATCH 048/163] New translations session.md (Uzbek) [skip ci] Update translations (Uzbek) session.md --- uz_UZ/the-basics/session.md | 261 ++++++++++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 uz_UZ/the-basics/session.md diff --git a/uz_UZ/the-basics/session.md b/uz_UZ/the-basics/session.md new file mode 100644 index 000000000..171779884 --- /dev/null +++ b/uz_UZ/the-basics/session.md @@ -0,0 +1,261 @@ +# Session + +[[toc]] + +## Introduction + +Session enables you to store user information across multiple requests, providing a stateful experience within the inherently stateless HTTP protocol. This user information is stored persistently on the server side. Goravel offers a unified interface for interacting with various persistent storage drivers. + +## Configuration + +The `session` configuration file is located at `config/session.go`. The default driver is `file`, which stores sessions in the `storage/framework/sessions` directory. Goravel allows you to create a custom `session` driver by implementing the `contracts/session/driver` interface. + +### Register Middleware + +By default, Goravel does not start a session automatically. However, it provides middleware to start a session. You can register the middleware in the `WithMiddleware` function in the `bootstrap/app.go` file, or you can add it to specific routes: + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithMiddleware(func(handler configuration.Middleware) { + handler.Append( + middleware.StartSession(), + ) + }). + WithConfig(config.Boot). + Create() +} +``` + +## Interacting With The Session + +### Retrieving Data + +You can use the `Get` method to retrieve data from the session. If the value does not exist, `nil` will be returned. + +```go +value := ctx.Request().Session().Get("key") +``` + +You may also pass a default value as the second argument to the `Get` method. This value will be returned if the specified key does not exist in the session: + +```go +value := ctx.Request().Session().Get("key", "default") +``` + +### Retrieving All Data + +If you would like to retrieve all data from the session, you may use the `All` method: + +```go +data := ctx.Request().Session().All() +``` + +### Retrieving a Subset of Data + +If you would like to retrieve a subset of the session data, you may use the `Only` method: + +```go +data := ctx.Request().Session().Only([]string{"username", "email"}) +``` + +### Determining If An Item Exists In The Session + +To determine if an item is present in the session, you may use the `Has` method. The `Has` method returns `true` if the item is present and is not `nil`: + +```go +if ctx.Request().Session().Has("user") { + // +} +``` + +To determine if an item is present and even if it is `nil`, you may use the `Exists` method: + +```go +if ctx.Request().Session().Exists("user") { + // +} +``` + +To determine if an item is not present in the session, you may use the `Missing` method: + +```go +if ctx.Request().Session().Missing("user") { + // +} +``` + +### Storing Data + +You can use the `Put` method to store data in the session: + +```go +ctx.Request().Session().Put("key", "value") +``` + +### Retrieving & Deleting Data + +If you would like to retrieve an item from the session and then delete it, you may use the `Pull` method: + +```go +value := ctx.Request().Session().Pull("key") +``` + +### Deleting Data + +The `Forget` method can be used to remove a piece of data from the session. If you would like to remove all data from the session, you can use the `Flush` method: + +```go +ctx.Request().Session().Forget("username", "email") + +ctx.Request().Session().Flush() +``` + +### Regenerating The Session ID + +Regenerating the session ID is often done in order to prevent malicious users from exploiting a session fixation attack on your application. You may regenerate the session ID using the `Regenerate` method: + +```go +ctx.Request().Session().Regenerate() +``` + +If you would like to regenerate the session ID and forget all data that was in the session, you may use the `Invalidate` method: + +```go +ctx.Request().Session().Invalidate() +``` + +Then, you need to save the new session to the cookie: + +```go +ctx.Response().Cookie(http.Cookie{ + Name: ctx.Request().Session().GetName(), + Value: ctx.Request().Session().GetID(), + MaxAge: facades.Config().GetInt("session.lifetime") * 60, + Path: facades.Config().GetString("session.path"), + Domain: facades.Config().GetString("session.domain"), + Secure: facades.Config().GetBool("session.secure"), + HttpOnly: facades.Config().GetBool("session.http_only"), + SameSite: facades.Config().GetString("session.same_site"), +}) +``` + +### Flash Data + +Flash data is session data that will only be available during the subsequent HTTP request, and then will be deleted. Flash data is useful for storing temporary messages such as status messages. You may use the `Flash` method to store flash data in the session: + +```go +ctx.Request().Session().Flash("status", "Task was successful!") +``` + +If you would like to keep your flash data around for an additional request, you may use the `Reflash` method: + +```go +ctx.Request().Session().Reflash() +``` + +If you would like to keep specific flash data around for an additional request, you may use the `Keep` method: + +```go +ctx.Request().Session().Keep("status", "username") +``` + +If you would like to keep specific data around for immediate use, you may use the `Now` method: + +```go +ctx.Request().Session().Now("status", "Task was successful!") +``` + +## Interacting With Session Manager + +### Building A Custom Session + +Use the `Session` facade to build a custom session. The `Session` facade provides the `BuildSession` method, which takes a driver instance and an optional session ID if you want to specify a custom session ID: + +```go +session := facades.Session().BuildSession(driver, "sessionID") +``` + +### Add Custom Session Drivers + +#### Implementing Driver + +To implement a custom session driver, driver must implement the `contracts/session/driver` interface. + +```go +// Driver is the interface for Session handlers. +type Driver interface { + // Close closes the session handler. + Close() error + // Destroy destroys the session with the given ID. + Destroy(id string) error + // Gc performs garbage collection on the session handler with the given maximum lifetime. + Gc(maxLifetime int) error + // Open opens a session with the given path and name. + Open(path string, name string) error + // Read reads the session data associated with the given ID. + Read(id string) (string, error) + // Write writes the session data associated with the given ID. + Write(id string, data string) error +} +``` + +#### Register Driver + +After implementing the driver, you only need to add it to the `config/session.go` configuration file: + +```go +// config/session.go +"default": "new", + +"drivers": map[string]any{ + "file": map[string]any{ + "driver": "file", + }, + "new": map[string]any{ + "driver": "custom", + "via": func() (session.Driver, error) { + return &CustomDriver{}, nil + }, + } +}, +``` + +### Retrieving driver instance + +Use the `Driver` method to retrieve the driver instance from the session manager. It accepts an optional driver name, if not provided, it returns the default driver instance: + +```go +driver, err := facades.Session().Driver("file") +``` + +### Starting A New Session + +```go +session := facades.Session().BuildSession(driver) +session.Start() +``` + +### Saving The Session Data + +```go +session := facades.Session().BuildSession(driver) +session.Start() +session.Save() +``` + +### Attaching the Session to the Request + +```go +session := facades.Session().BuildSession(driver) +session.Start() +ctx.Request().SetSession(session) +``` + +### Checking if request has session + +```go +if ctx.Request().HasSession() { + // +} +``` From 5946a7a01574dbc468429a4ff3e18c35cff2a13e Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:50 +0800 Subject: [PATCH 049/163] New translations validation.md (Uzbek) [skip ci] Update translations (Uzbek) validation.md --- uz_UZ/the-basics/validation.md | 567 +++++++++++++++++++++++++++++++++ 1 file changed, 567 insertions(+) create mode 100644 uz_UZ/the-basics/validation.md diff --git a/uz_UZ/the-basics/validation.md b/uz_UZ/the-basics/validation.md new file mode 100644 index 000000000..7a78fc2f6 --- /dev/null +++ b/uz_UZ/the-basics/validation.md @@ -0,0 +1,567 @@ +# Validation + +[[toc]] + +## Introduction + +Goravel provides several different approaches to validate your application's incoming data. It is most common to use the `Validate` method available on all incoming HTTP requests. Goravel includes a wide variety of convenient validation rules. + +## Validation Quickstart + +Let's take a closer look at a complete example of how to validate a form and return error messages to the user. This overview will provide you with a general understanding of how to validate incoming request data using Goravel. + +### Defining The Routes + +First, let's assume we have the following routes defined in our `routes/web.go` file: + +```go +import "goravel/app/http/controllers" + +postController := controllers.NewPostController() +facades.Route().Get("/post/create", postController.Create) +facades.Route().Post("/post", postController.Store) +``` + +The `GET` route displays a form for creating a new blog post. The `POST` route stores the new post in the database. + +### Creating The Controller + +Next, let's take a look at a simple controller that handles incoming requests to these routes. We'll leave the `Store` method empty for now: + +```go +package controllers + +import ( + "github.com/goravel/framework/contracts/http" +) + +type PostController struct {} + +func NewPostController() *PostController { + return &PostController{} +} + +func (r *PostController) Store(ctx http.Context) {} +``` + +### Writing The Validation Logic + +Now we are ready to fill in our `Store` method with the logic to validate the new blog post. + +```go +func (r *PostController) Store(ctx http.Context) { + validator, err := ctx.Request().Validate(map[string]string{ + "title": "required|max_len:255", + "body": "required", + "code": "required|regex:^\d{4,6}$", + }) +} +``` + +### Nested Attributes + +If the incoming HTTP request contains "nested" field data, you may specify these fields in your validation rules using the "dot" syntax: + +```go +validator, err := ctx.Request().Validate(map[string]string{ + "title": "required|max_len:255", + "author.name": "required", + "author.description": "required", +}) +``` + +### Slice Validation + +If the incoming HTTP request contains "array" field data, you may specify these fields in your validation rules using the `*` syntax: + +```go +validator, err := ctx.Request().Validate(map[string]string{ + "tags.*": "required", +}) +``` + +## Form Request Validation + +### Creating Form Requests + +For more complex validation scenarios, you may wish to create a "form request". Form requests are custom request classes that encapsulate their own validation and authorization logic. To create a form request class, you may use the `make:request` Artisan CLI command: + +```go +./artisan make:request StorePostRequest +./artisan make:request user/StorePostRequest +``` + +The generated form request class will be placed in the `app/http/requests` directory. If this directory does not exist, it will be created when you run the `make:request` command. Each form request generated by Goravel has six methods: `Authorize`, `Rules`. In addition, you can customize the `Filters`, `Messages`, `Attributes` and `PrepareForValidation` methods for further operations. + +The `Authorize` method is responsible for determining if the currently authenticated user can perform the action represented by the request, while the `Rules` method returns the validation rules that should apply to the request's data: + +```go +package requests + +import ( + "mime/multipart" + + "github.com/goravel/framework/contracts/http" + "github.com/goravel/framework/contracts/validation" +) + +type StorePostRequest struct { + Name string `form:"name" json:"name"` + File *multipart.FileHeader `form:"file" json:"file"` + Files []*multipart.FileHeader `form:"files" json:"files"` +} + +func (r *StorePostRequest) Authorize(ctx http.Context) error { + return nil +} + +func (r *StorePostRequest) Rules(ctx http.Context) map[string]string { + return map[string]string{ + // The keys are consistent with the incoming keys. + "name": "required|max_len:255", + "file": "required|file", + "files": "required|array", + "files.*": "required|file", + } +} +``` + +Then you can use the `ValidateRequest` method to validate the request in the controller: + +```go +func (r *PostController) Store(ctx http.Context) { + var storePost requests.StorePostRequest + errors, err := ctx.Request().ValidateRequest(&storePost) +} +``` + +Check more rules in the [Available Validation Rules](#available-validation-rules) section. + +> Note that since `form` passed values ​​are of `string` type by default, all fields in request should also be of `string` type, otherwise please use `JSON` to pass values. + +### Authorizing Form Requests + +The form request class also contains an `Authorize` method. Within this method, you may determine if the authenticated user actually has the authority to update a given resource. For example, you may determine if a user actually owns a blog comment they are attempting to update. Most likely, you will interact with your [authorization gates and policies](../security/authorization.md) within this method: + +```go +func (r *StorePostRequest) Authorize(ctx http.Context) error { + var comment models.Comment + facades.Orm().Query().First(&comment) + if comment.ID == 0 { + return errors.New("no comment is found") + } + + if !facades.Gate().Allows("update", map[string]any{ + "comment": comment, + }) { + return errors.New("can't update comment") + } + + return nil +} +``` + +`error` will be passed to the return value of `ctx.Request().ValidateRequest`. + +### Filter Input Data + +You can format the input data by improving the `Filters` method of the form request. This method should return an map of `attribute/filter`: + +```go +func (r *StorePostRequest) Filters(ctx http.Context) map[string]string { + return map[string]string{ + "name": "trim", + } +} +``` + +### Customizing The Error Messages + +You may customize the error messages used by the form request by overriding the `Messages` method. This method should return an array of attribute / rule pairs and their corresponding error messages: + +```go +func (r *StorePostRequest) Messages() map[string]string { + return map[string]string{ + "title.required": "A title is required", + "body.required": "A message is required", + } +} +``` + +### Customizing The Validation Attributes + +Many of Goravel's built-in validation rule error messages contain an `:attribute` placeholder. If you would like the `:attribute` placeholder of your validation message to be replaced with a custom attribute name, you may specify the custom names by overriding the `Attributes` method. This method should return an array of attribute / name pairs: + +```go +func (r *StorePostRequest) Attributes() map[string]string { + return map[string]string{ + "email": "email address", + } +} +``` + +### Preparing Input For Validation + +If you need to prepare or sanitize any data from the request before you apply your validation rules, you may use the `PrepareForValidation` method: + +```go +func (r *StorePostRequest) PrepareForValidation(ctx http.Context, data validation.Data) error { + if name, exist := data.Get("name"); exist { + return data.Set("name", name.(string)+"1") + } + return nil +} +``` + +## Manually Creating Validators + +If you do not want to use the `Validate` method on the request, you may create a validator instance manually using the `facades.Validator`. The `Make` method of the facade generates a new validator instance: + +```go +func (r *PostController) Store(ctx http.Context) http.Response { + validator, _ := facades.Validation().Make( + ctx, + map[string]any{ + "name": "Goravel", + }, + map[string]string{ + "title": "required|max_len:255", + "body": "required", + }) + + if validator.Fails() { + // Return fail + } + + var user models.User + err := validator.Bind(&user) + ... +} +``` + +The first argument passed to the `Make` method is the data under validation which can be `map[string]any` or `struct`. The second argument is an array of validation rules to be applied to the data. + +### Customizing The Error Messages + +If needed, you may provide custom error messages that a validator instance should use instead of the default error messages provided by Goravel. You may pass the custom messages as the third argument to the `Make` method (also applicable to `ctx.Request().Validate()`): + +```go +validator, err := facades.Validation().Make(ctx, input, rules, validation.Messages(map[string]string{ + "required": "The :attribute field is required.", +})) +``` + +### Specifying A Custom Message For A Given Attribute + +Sometimes you may wish to specify a custom error message only for a specific attribute. You may do so using "dot" notation. Specify the attribute's name first, followed by the rule (also applicable to `ctx.Request().Validate()`): + +```go +validator, err := facades.Validation().Make(ctx, input, rules, validation.Messages(map[string]string{ + "email.required": "We need to know your email address!", +})) +``` + +### Specifying Custom Attribute Values + +Many of Goravel's built-in error messages include an `:attribute` placeholder that is replaced with the name of the field or attribute under validation. To customize the values used to replace these placeholders for specific fields, you may pass an array of custom attributes as the third argument to the `Make` method (also applicable to `ctx.Request().Validate()`): + +```go +validator, err := facades.Validation().Make(ctx, input, rules, validation.Attributes(map[string]string{ + "email": "email address", +})) +``` + +### Format Data Before Validation + +You can format the data before validating the data for more flexible data validation, and you can pass the method of formatting the data as the third parameter to the `Make` method (also applicable to `ctx.Request().Validate()`): + +```go +import ( + validationcontract "github.com/goravel/framework/contracts/validation" + "github.com/goravel/framework/validation" +) + +func (r *PostController) Store(ctx http.Context) http.Response { + validator, err := facades.Validation().Make(ctx, input, rules, + validation.PrepareForValidation(func(ctx http.Context, data validationcontract.Data) error { + if name, exist := data.Get("name"); exist { + return data.Set("name", name) + } + + return nil + })) + + ... +} +``` + +## Working With Validated Input + +After validating incoming request data using form requests or manually created validator instances, you still want to bind the request data to a `struct`, there are two ways to do this: + +1. Use the `Bind` method, this will bind all incoming data, including unvalidated data: + +```go +validator, err := ctx.Request().Validate(rules) +var user models.User +err := validator.Bind(&user) + +validator, err := facades.Validation().Make(ctx, input, rules) +var user models.User +err := validator.Bind(&user) +``` + +2. The incoming data is automatically bound to the form when you use request for validation: + +```go +var storePost requests.StorePostRequest +errors, err := ctx.Request().ValidateRequest(&storePost) +fmt.Println(storePost.Name) +``` + +## Working With Error Messages + +### Retrieving one Error Message For A Field (Random) + +```go +validator, err := ctx.Request().Validate(rules) +validator, err := facades.Validation().Make(ctx, input, rules) + +message := validator.Errors().One("email") +``` + +### Retrieving All Error Messages For A Field + +```go +messages := validator.Errors().Get("email") +``` + +### Retrieving All Error Messages For All Fields + +```go +messages := validator.Errors().All() +``` + +### Determining If Error Messages Exist For A Field + +```go +if validator.Errors().Has("email") { + // +} +``` + +## Available Validation Rules + +Below is a list of all available validation rules and their function: + +| Name | Description | +| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `required` | Check value is required and cannot be zero value. For example, field type is `bool`, the passing value is `false`, it can not pass the validation. | +| `required_if` | `required_if:anotherfield,value,...` The field under validation must be present and not empty if the anotherField field is equal to any value. | +| `required_unless` | `required_unless:anotherfield,value,...` The field under validation must be present and not empty unless the anotherField field is equal to any value. | +| `required_with` | `required_with:foo,bar,...` The field under validation must be present and not empty only if any of the other specified fields are present. | +| `required_with_all` | `required_with_all:foo,bar,...` The field under validation must be present and not empty only if all of the other specified fields are present. | +| `required_without` | `required_without:foo,bar,...` The field under validation must be present and not empty only when any of the other specified fields are not present. | +| `required_without_all` | `required_without_all:foo,bar,...` The field under validation must be present and not empty only when all of the other specified fields are not present. | +| `int` | Check value is `intX` `uintX` type, and support size checking. eg: `int` `int:2` `int:2,12`. Notice: [Points for using rules](#int) | +| `uint` | Check value is `uint(uintX)` type, `value >= 0` | +| `bool` | Check value is bool string(`true`: "1", "on", "yes", "true", `false`: "0", "off", "no", "false"). | +| `string` | Check value is string type, and support size checking. eg:`string` `string:2` `string:2,12` | +| `float` | Check value is `float(floatX)` type | +| `slice` | Check value is slice type(`[]intX` `[]uintX` `[]byte` `[]string`) | +| `in` | `in:foo,bar,…` Check if the value is in the given enumeration | +| `not_in` | `not_in:foo,bar,…` Check if the value is not in the given enumeration | +| `starts_with` | `starts_with:foo` Check if the input string value is starts with the given sub-string | +| `ends_with` | `ends_with:foo` Check if the input string value is ends with the given sub-string | +| `between` | `between:min,max` Check that the value is a number and is within the given range | +| `max` | `max:value` Check value is less than or equal to the given value(`intX` `uintX` `floatX`) | +| `min` | `min:value` Check value is greater than or equal to the given value(`intX` `uintX` `floatX`) | +| `eq` | `eq:value` Check that the input value is equal to the given value | +| `ne` | `ne:value` Check that the input value is not equal to the given value | +| `lt` | `lt:value` Check value is less than the given value(`intX` `uintX` `floatX`) | +| `gt` | `gt:value` Check value is greater than the given value(`intX` `uintX` `floatX`) | +| `len` | `len:value` Check value length is equals to the given size(`string` `array` `slice` `map`) | +| `min_len` | `min_len:value` Check the minimum length of the value is the given size(`string` `array` `slice` `map`) | +| `max_len` | `max_len:value` Check the maximum length of the value is the given size(`string` `array` `slice` `map`) | +| `email` | Check value is email address string | +| `array` | Check value is array, slice type | +| `map` | Check value is a MAP type | +| `eq_field` | `eq_field:field` Check that the field value is equals to the value of another field | +| `ne_field` | `ne_field:field` Check that the field value is not equals to the value of another field | +| `gt_field` | `gt_field:field` Check that the field value is greater than the value of another field | +| `gte_field` | `gte_field:field` Check that the field value is greater than or equal to the value of another field | +| `lt_field` | `lt_field:field` Check that the field value is less than the value of another field | +| `lte_field` | `lte_field:field` Check if the field value is less than or equal to the value of another field | +| `file` | Verify if it is an uploaded file | +| `image` | Check if it is an uploaded image file and support suffix check | +| `date` | Check the field value is date string | +| `gt_date` | `gt_date:value` Check that the input value is greater than the given date string | +| `lt_date` | `lt_date:value` Check that the input value is less than the given date string | +| `gte_date` | `gte_date:value` Check that the input value is greater than or equal to the given date string | +| `lte_date` | `lte_date:value` Check that the input value is less than or equal to the given date string | +| `alpha` | Verify that the value contains only alphabetic characters | +| `alpha_num` | Check that only letters, numbers are included | +| `alpha_dash` | Check to include only letters, numbers, dashes ( - ), and underscores ( \_ ) | +| `json` | Check value is JSON string | +| `number` | Check value is number string `>= 0` | +| `full_url` | Check value is full URL string(must start with http,https) | +| `ip` | Check value is IP(v4 or v6) string | +| `ipv4` | Check value is IPv4 string | +| `ipv6` | Check value is IPv6 string | +| `regex` | Check if the value can pass the regular verification | +| `uuid` | Check value is UUID string | +| `uuid3` | Check value is UUID3 string | +| `uuid4` | Check value is UUID4 string | +| `uuid5` | Check value is UUID5 string | + +### Points For Using Rules + +#### int + +When using `ctx.Request().Validate(rules)` for validation, the incoming `int` type data will be parsed by `json.Unmarshal` into `float64` type, which will cause the int rule validation to fail. + +**Solutions** + +Option 1: Add [`validation.PrepareForValidation`](#Format-Data-Before-Validation), format the data before validating the data; + +Option 2: Use `facades.Validation().Make()` for rule validation; + +## Custom Validation Rules + +Goravel provides a variety of helpful validation rules; however, you may wish to specify some of your own. One method of registering custom validation rules is using rule objects. To generate a new rule object, you can simply use the `make:rule` Artisan command. + +### Creating Custom Rules + +For instance, if you want to verify that a string is uppercase, you can create a rule with this command. Goravel will then save this new rule in the `app/rules` directory. If this directory does not exist, Goravel will create it when you run the Artisan command to create your rule. + +```go +./artisan make:rule Uppercase +./artisan make:rule user/Uppercase +``` + +### Defining Custom Rules + +After creating the rule, we need to define its behavior. A rule object has two methods: `Passes` and `Message`. The Passes method receives all data, including the data to be validated and the validation parameters. It should return `true` or `false` depending on whether the attribute value is valid. The `Message` method should return the error message for validation that should be used when the validation fails. + +```go +package rules + +import ( + "strings" + + "github.com/goravel/framework/contracts/validation" +) + +type Uppercase struct { +} + +// Signature The name of the rule. +func (receiver *Uppercase) Signature() string { + return "uppercase" +} + +// Passes Determine if the validation rule passes. +func (receiver *Uppercase) Passes(ctx context.Context, data validation.Data, val any, options ...any) bool { + return strings.ToUpper(val.(string)) == val.(string) +} + +// Message Get the validation error message. +func (receiver *Uppercase) Message(ctx context.Context) string { + return "The :attribute must be uppercase." +} +``` + +### Register Custom Rules + +A new rule created by `make:rule` will be registered automatically in the `bootstrap/rules.go::Rules()` function and the function will be called by `WithRules`. You need register the rule manually if you create the rule file by yourself. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithRules(Rules). + WithConfig(config.Boot). + Create() +} +``` + +## Available Validation Filters + +| Name | Description | +| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `int/toInt` | Convert value(string/intX/floatX) to `int` type `v.FilterRule("id", "int")` | +| `uint/toUint` | Convert value(string/intX/floatX) to `uint` type `v.FilterRule("id", "uint")` | +| `int64/toInt64` | Convert value(string/intX/floatX) to `int64` type `v.FilterRule("id", "int64")` | +| `float/toFloat` | Convert value(string/intX/floatX) to `float` type | +| `bool/toBool` | Convert string value to bool. (`true`: "1", "on", "yes", "true", `false`: "0", "off", "no", "false") | +| `trim/trimSpace` | Clean up whitespace characters on both sides of the string | +| `ltrim/trimLeft` | Clean up whitespace characters on left sides of the string | +| `rtrim/trimRight` | Clean up whitespace characters on right sides of the string | +| `int/integer` | Convert value(string/intX/floatX) to `int` type `v.FilterRule("id", "int")` | +| `lower/lowercase` | Convert string to lowercase | +| `upper/uppercase` | Convert string to uppercase | +| `lcFirst/lowerFirst` | Convert the first character of a string to lowercase | +| `ucFirst/upperFirst` | Convert the first character of a string to uppercase | +| `ucWord/upperWord` | Convert the first character of each word to uppercase | +| `camel/camelCase` | Convert string to camel naming style | +| `snake/snakeCase` | Convert string to snake naming style | +| `escapeJs/escapeJS` | Escape JS string. | +| `escapeHtml/escapeHTML` | Escape HTML string. | +| `str2ints/strToInts` | Convert string to int slice `[]int` | +| `str2time/strToTime` | Convert date string to `time.Time`. | +| `str2arr/str2array/strToArray` | Convert string to string slice `[]string` | + +## Custom filter + +Goravel provides a variety of helpful filters, however, you may wish to specify some of your own. + +### Creating Custom Filters + +To generate a new rule object, you can simply use the `make:filter` Artisan command. Let's use this command to generate a rule that converts a string to an integer. This rule is already built into the framework, we just create it as an example. Goravel will save this new filter in the `app/filters` directory. If this directory does not exist, Goravel will create it when you run the Artisan command to create the rule: + +```go +./artisan make:filter ToInt +./artisan make:filter user/ToInt +``` + +### Defining Custom Filters + +One filter contains two methods: `Signature` and `Handle`. The `Signature` method sets the name of the filter. The `Handle` method performs the specific filtering logic: + +```go +package filters + +import ( + "strings" + + "github.com/spf13/cast" + "github.com/goravel/framework/contracts/validation" +) + +type ToInt struct { +} + +// Signature The signature of the filter. +func (receiver *ToInt) Signature() string { + return "ToInt" +} + +// Handle defines the filter function to apply. +func (receiver *ToInt) Handle(ctx context.Context) any { + return func (val any) int { + return cast.ToString(val) + } +} +``` + +### Register Custom Filters + +A new rule created by `make:filter` will be registered automatically in the `bootstrap/filters.go::Filters()` function and the function will be called by `WithFilters`. You need register the rule manually if you create the rule file by yourself. + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithFilters(Filters). + WithConfig(config.Boot). + Create() +} +``` From 566c0ea27595c78b719e22e552899622cb1e5f5b Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:51 +0800 Subject: [PATCH 050/163] New translations views.md (Uzbek) [skip ci] Update translations (Uzbek) views.md --- uz_UZ/the-basics/views.md | 172 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 uz_UZ/the-basics/views.md diff --git a/uz_UZ/the-basics/views.md b/uz_UZ/the-basics/views.md new file mode 100644 index 000000000..5fa66f8b6 --- /dev/null +++ b/uz_UZ/the-basics/views.md @@ -0,0 +1,172 @@ +# Views + +[[toc]] + +## Introduction + +Of course, it's not practical to return entire HTML document strings directly from your routes and controllers. Thankfully, views provide a convenient way to place all of our HTML in separate files. Views separate your controller / application logic from your presentation logic and are stored in the `resources/views` directory. + +## Creating & Rendering Views + +When using the Goravel default template `html/template`, you can create views by adding a file with the `.tmpl` extension in the application `resources/views` directory. + +``` +// resources/views/welcome.tmpl +{{ define "welcome.tmpl" }} + + +

Hello, {{ .name }}

+ + +{{ end }} +``` + +After creating the view, you can use the `View` method to return the view from a route or controller in the application: + +```go +facades.Route().Get("/", func(ctx http.Context) http.Response { + return ctx.Response().View().Make("welcome.tmpl", map[string]any{ + "name": "Goravel", + }) +}) +``` + +### Nested View Directories + +Views may also be nested within subdirectories of the `resources/views` directory. For example, if your view is stored at `resources/views/admin/profile.tmpl`, you can return it from one of your application's routes or controllers, note that the view needs to be defined as `define "admin/profile.tmpl"` as shown below: + +```go +// resources/views/admin/profile.tmpl +{{ define "admin/profile.tmpl" }} +

Welcome to the Admin Panel

+{{ end }} + +ctx.Response().View().Make("admin/profile.tmpl", map[string]any{ + "name": "Goravel", +}) +``` + +### Creating The First Available View + +Using the `First` method, you can use the first view that exists in a given array of views. This may be useful if your application or package allows views to be customized or overwritten: + +```go +ctx.Response().View().First([]string{"custom/admin.tmpl", "admin.tmpl"}, map[string]any{ + "name": "Goravel", +}) +``` + +### Determining If A View Exists + +If you need to determine if a view exists, you can use the `facades.View()` method: + +```go +if facades.View().Exist("welcome.tmpl") { + // ... +} +``` + +## Passing Data To Views + +As you saw in the previous examples, you may pass an array of data to views to make that data available to the view. Please note, the format of the passed data needs to change according to the template driver used, in the following example, using the default `html/template` driver: + +```go +facades.Route().Get("/", func(ctx http.Context) http.Response { + return ctx.Response().View().Make("welcome.tmpl", map[string]any{ + "name": "Goravel", + }) +}) +``` + +### Sharing Data With All Views + +Occasionally, you may need to share data with all views that are rendered by your application. You may do so using the `Share` function in `facades.View()`. Typically, you should place calls to the `Share` function in the `bootstrap/app.go::WithCallback` function: + +```go +func Boot() contractsfoundation.Application { + return foundation.Setup(). + WithConfig(config.Boot). + WithCallback(func() { + facades.View().Share("key", "value") + }). + Create() +} +``` + +## CSRF Token Middleware + +This middleware can be applied to routes to ensure that requests are coming from authenticated sources to against Cross-Site Request Forgery (CSRF) attacks. + +::: v-pre + +1. Register the middleware (`github.com/goravel/framework/http/middleware::VerifyCsrfToken(exceptPaths)`) to global or a specific route. +2. Add `` to your form in the view file, or add `X-CSRF-TOKEN={{ .csrf_token }}` to your request header to include the CSRF token. +3. The middleware will automatically verify the token on form submission. + ::: + +## Register Custom Delims And Functions + +You can register custom Delims and functions to be used within your views, they can be registered in the configuration `http.drivers.*.template`. + +For the gin driver: + +```go +// config/http.go +import ( + "html/template" + + "github.com/gin-gonic/gin/render" + "github.com/goravel/gin" +) + +"template": func() (render.HTMLRender, error) { + return gin.NewTemplate(gin.RenderOptions{ + Delims: &gin.Delims{ + Left: "{{", + Right: "}}", + }, + FuncMap: template.FuncMap{ + // Add custom template functions here + }, + }) +}, +``` + +For the fiber driver: + +```go +// config/http.go +import ( + "github.com/gofiber/fiber/v2" + "github.com/gofiber/template" + "github.com/gofiber/template/html/v2" + "github.com/goravel/framework/support/path" +) + +"template": func() (fiber.Views, error) { + engine := &html.Engine{ + Engine: template.Engine{ + Left: "{{", + Right: "}}", + Directory: path.Resource("views"), + Extension: ".tmpl", + LayoutName: "embed", + // Add custom template functions here + Funcmap: make(map[string]interface{}), + }, + } + + engine.AddFunc(engine.LayoutName, func() error { + return fmt.Errorf("layoutName called unexpectedly") + }) + return engine, nil +}, +``` + +## Custom Template Engines + +You can create your own custom template engines by implementing the `render.HTMLRender` interface of gin or the `fiber.Views` interface of fiber. After creating your custom engine, you can register it to the configuration `http.drivers.*.template`. + +## Advanced Features + +`http/template` is the default template engine, you can refer to the official documentation for more advanced features: https://pkg.go.dev/html/template. From 05d90c65872d93a4d254a9001429a01f530b23cc Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:52 +0800 Subject: [PATCH 051/163] New translations history.md (Uzbek) [skip ci] Update translations (Uzbek) history.md --- uz_UZ/upgrade/history.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 uz_UZ/upgrade/history.md diff --git a/uz_UZ/upgrade/history.md b/uz_UZ/upgrade/history.md new file mode 100644 index 000000000..920e4b67f --- /dev/null +++ b/uz_UZ/upgrade/history.md @@ -0,0 +1,17 @@ +# History Upgrade + +- [Upgrading To v1.15 From v1.14](v1.15.md) +- [Upgrading To v1.14 From v1.13](v1.14.md) +- [Upgrading To v1.13 From v1.12](v1.13.md) +- [Upgrading To v1.12 From v1.11](v1.12.md) +- [Upgrading To v1.11 From v1.10](v1.11.md) +- [Upgrading To v1.10 From v1.9](v1.10.md) +- [Upgrading To v1.9 From v1.8](v1.9.md) +- [Upgrading To v1.8 From v1.7](v1.8.md) +- [Upgrading To v1.7 From v1.6](v1.7.md) +- [Upgrading To v1.6 From v1.5](v1.6.md) +- [Upgrading To v1.5 From v1.4](v1.5.md) +- [Upgrading To v1.4 From v1.3](v1.4.md) +- [Upgrading To v1.3 From v1.2](v1.3.md) +- [Upgrading To v1.2 From v1.1](v1.2.md) +- [Upgrading To v1.1 From v1.0](v1.1.md) From 15d899cbd8e8f8ddaffc6a642005c8af8f0b69d4 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:53 +0800 Subject: [PATCH 052/163] New translations v1.1.md (Uzbek) [skip ci] Update translations (Uzbek) v1.1.md --- uz_UZ/upgrade/v1.1.md | 76 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 uz_UZ/upgrade/v1.1.md diff --git a/uz_UZ/upgrade/v1.1.md b/uz_UZ/upgrade/v1.1.md new file mode 100644 index 000000000..9cfb5960f --- /dev/null +++ b/uz_UZ/upgrade/v1.1.md @@ -0,0 +1,76 @@ +# Upgrading To v1.1 From v1.0 + +[[toc]] + +## High Impact Changes + +- [Updating Dependencies](#updating-dependencies) +- [Update Providers](#update-providers) +- [Add Config](#add-config) + +## Medium Impact Changes + +- [facades.Cache Add Methods](#facades-cache-add-methods) + +## Low Impact Changes + +- [Add facades.Auth](#add-facades-auth) + +## Upgrade Guide + +**Estimated Upgrade Time: 1 Minutes** + +### Updating Dependencies + +**Likelihood Of Impact: High** + +Update dependencies in the `go.mod` file: + +```go +github.com/goravel/framework v1.1.1 +``` + +### Update Providers + +**Likelihood Of Impact: High** + +Add Auth Provider in the `config.app.go` file: + +```go +"github.com/goravel/framework/auth" + +"providers": []contracts.ServiceProvider{ + ... + &mail.ServiceProvider{}, + &auth.ServiceProvider{}, + &providers.AppServiceProvider{}, + ... +} +``` + +### Add Config + +**Likelihood Of Impact: High** + +Add file in the `config` directory: + +1. [auth.go](https://github.com/goravel/goravel/blob/v1.1.1/config/auth.go) +2. [jwt.go](https://github.com/goravel/goravel/blob/v1.1.1/config/jwt.go) + +### Add facades.Cache methods + +**Likelihood Of Impact: Medium** + +Add methods: + +1. [facades.Cache.GetBool](https://github.com/goravel/framework/blob/87c7fa9b95e45fcf4f88a502f1a1adc213527ae1/contracts/cache/store.go#L9) +2. [facades.Cache.GetInt](https://github.com/goravel/framework/blob/87c7fa9b95e45fcf4f88a502f1a1adc213527ae1/contracts/cache/store.go#L10) +3. [facades.Cache.GetString](https://github.com/goravel/framework/blob/87c7fa9b95e45fcf4f88a502f1a1adc213527ae1/contracts/cache/store.go#L11) + +You need to implement the new three interfaces if you are using [Adding Custom Cache Drivers](https://github.com/goravel/docs/blob/master/digging-deeper/cache.md#adding-custom-cache-drivers). + +### Add facades.Auth + +**Likelihood Of Impact: Low** + +Add Authentication [facades.Auth](../security/authentication.md)。 From 9d3b9b3cc6366afbb02ae7cd1214be0526a7ecce Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:54 +0800 Subject: [PATCH 053/163] New translations v1.10.md (Uzbek) [skip ci] Update translations (Uzbek) v1.10.md --- uz_UZ/upgrade/v1.10.md | 226 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 uz_UZ/upgrade/v1.10.md diff --git a/uz_UZ/upgrade/v1.10.md b/uz_UZ/upgrade/v1.10.md new file mode 100644 index 000000000..c5921b34e --- /dev/null +++ b/uz_UZ/upgrade/v1.10.md @@ -0,0 +1,226 @@ +# Upgrading To v1.10 From v1.9 + +[[toc]] + +## Exciting New Features 🎉 + +- [Add facades.Crypt(1.10.0)](#encryption) +- [Add facades.Hash(1.10.0)](#hashing) +- [Add Rate Limiting For Routing(1.10.0)](#add-rate-limiting-for-routing) + +## Enhancements 🚀 + +- [Optimize HTTP startup mode(1.10.0)](#optimize-http-startup-mode) +- [Optimize GRPC startup mode(1.10.0)](#optimize-grpc-startup-mode) +- [Add configuration to control log output to console(1.10.0)](#add-configuration-to-control-log-output-to-console) +- [Request modify and add methods(1.10.0)](#request-modify-and-add-methods) +- [Queue support delayed dispatching(1.10.0)](#queue-support-delayed-dispatching) +- [The Connection in ORM supports set table prefix and singular(1.10.0)](#the-connection-in-orm-supports-set-table-prefix-and-singular) +- [Add docker-compose.yml file(1.10.0)](#add-docker-compose-yml-file) +- [Optimize Orm(1.10.0)](#optimize-orm) +- [Support multiple SQL in migration file(1.10.0)](#support-multiple-sql-in-migration-file) +- [Add minio driver for File Storage(1.10.0)](#add-minio-driver-for-file-storage) +- [contracts/http add status mapping of net/http(1.10.0)](#contracts-http-add-status-mapping-of-net-http) + +## Breaking Changes 🛠 + +- [APP_KEY required(1.10.0)](#app-key-required) +- [Add ctx parameter to the methods under Form Request(1.10.0)](#add-ctx-parameter-to-the-methods-under-form-request) +- [facades.Auth.Parse adds payload returns(1.10.0)](#facades-auth-parse-add-payload-returns) +- [Some methods of Orm add new return values(1.10.0)](#some-methods-of-orm-add-new-return-values) + +## Upgrade Guide + +**Estimated Upgrade Time: 20 Minutes** + +### Updating Dependencies + +Update dependencies in the `go.mod` file: + +``` +go get -u github.com/goravel/framework@v1.10.0 && go mod tidy +``` + +### Encryption + +Version: v1.10.0 + +Add `facades.Crypt`: + +1. add `&crypt.ServiceProvider{}` to the `providers` item in the [config/app.go](https://github.com/goravel/goravel/blob/v1.10.x/config/app.go) file; + +[For Detail](../security/encryption.md) + +### Hashing + +Version: v1.10.0 + +Add `facades.Hash`: + +1. add `&hash.ServiceProvider{}` to the `providers` item in the [config/app.go](https://github.com/goravel/goravel/blob/v1.10.x/config/app.go) file; + +2. Add [config/hashing.go](https://github.com/goravel/goravel/blob/v1.10.x/config/hashing.go) file; + +[For Detail](../security/hashing.md) + +### Add Rate Limiting For Routing + +Version: v1.10.0 + +[For Detail](../the-basics/routing.md#Rate-Limiting) + +### Optimize HTTP startup mode + +Version: v1.10.0 + +1. Add `config/http.go` configuration, [For Detail](https://github.com/goravel/goravel/blob/v1.10.x/config/http.go); +2. The `facades.Route.Run` method no longer needs to pass parameters, by default use `http.host` and `http.port`(you don't need to modify the code, it's backward compatible); +3. The `facades.Route.RunTLS` method no longer needs to pass parameters, by default use `http.tls.host`, `http.tls.port`, `http.tls.ssl.cert` and `http.tls.ssl.key`, if you are using it, you need to modify the code; +4. Add `facades.Route.RunTLSWithCert` method, [For Detail](../the-basics/routing.md#start-server); +5. Move `app.url`, `app.host` to `http.url`, `http.host`; + +### Optimize GRPC startup mode + +Version: v1.10.0 + +The `facades.Grpc.Run` method no longer needs to pass parameters, by default use `grpc.host` and `grpc.port`(you don't need to modify the code, it's backward compatible); + +### Add configuration to control log output to console + +Version: v1.10.0 + +Add `print` configuration to `single`, `daily` channel in the `config/logging.go` file, it can control log output to console, [For Detail](https://github.com/goravel/goravel/blob/v1.10.x/config/logging.go); + +### Request modify and add methods + +Version: v1.10.0 + +1. The `Input` method is changed from only getting routing parameters to getting data according to the following order: `json`, `form`, `query`, `route`。Note: `json` can only get one-dimensional data, otherwise it will return empty; +2. Add `Route` method to replace the original `Input` method; +3. The default value of `Query` and `Form` methods are modified to be unnecessary; +4. Add methods as shown below: + +| Method | Action | +| ---------- | --------------------------------------------------------------------------------------------------------- | +| Route | [Retrieving An Route Value](../the-basics/request.md#Retrieving-An-Input-Value) | +| RouteInt | [Retrieving An Route Value](../the-basics/request.md#Retrieving-An-Input-Value) | +| RouteInt64 | [Retrieving An Route Value](../the-basics/request.md#Retrieving-An-Input-Value) | +| QueryInt | [Retrieving Input From The Query String](../the-basics/request.md#Retrieving-Input-From-The-Query-String) | +| QueryInt64 | [Retrieving Input From The Query String](../the-basics/request.md#Retrieving-Input-From-The-Query-String) | +| QueryBool | [Retrieving Input From The Query String](../the-basics/request.md#Retrieving-Input-From-The-Query-String) | +| InputInt | [Retrieving An Input Value](../the-basics/request.md#Retrieving-An-Input-Value) | +| InputInt64 | [Retrieving An Input Value](../the-basics/request.md#Retrieving-An-Input-Value) | +| InputBool | [Retrieving An Input Value](../the-basics/request.md#Retrieving-An-Input-Value) | +| Json | [Retrieving Json](../the-basics/request.md#Retrieving-Json) | + +### Queue support delayed dispatching + +Version: v1.10.0 + +Add `Delay` method, [For Detail](../digging-deeper/queues.md#Delayed-Dispatching) + +### The Connection in ORM supports set table prefix and singular + +Version: v1.10.0 + +1. `Model` supports specify table name, [For Detail](../orm/getting-started.md#指定表名); +2. Add new keys to `connection` of `config/database.go`: + +`prefix`: Set prefix for table name; +`singular`: Set the table name to use singular or plural; + +[For Detail](https://github.com/goravel/goravel/blob/v1.10.x/config/database.go) + +### Add docker-compose.yml file + +Version: v1.10.0 + +You can quickly start the service with the following command: + +``` +docker-compose build +docker-compose up +``` + +### Optimize Orm + +Version: v1.10.0 + +1. Add the following methods: + +| Functions | Action | +| -------------- | ---------------------------------------------------------- | +| FirstOr | [Query or return data through callback](#Query-one-line) | +| FirstOrNew | [Retrieving Or New Models](#Retrieving-Or-Creating-Models) | +| FirstOrFail | [Not Found Error](#Not-Found-Error) | +| UpdateOrCreate | [Update or create](#Update-or-create) | + +2. An error was reported like this before, but now it's supported: + +```go +query := facades.Orm.Query() +query = query.Where() +``` + +### Support multiple SQL in migration file + +Version: v1.10.0 + +Previously, only one SQL statement was supported in the migration file, but now multiple statements are supported. + +### Add minio driver for File Storage + +Version: v1.10.0 + +Add minio configuration, [For Detail](https://github.com/goravel/goravel/blob/v1.10.x/config/filesystems.go). + +### contracts/http add status mapping of net/http + +Version: v1.10.0 + +You can use status codes such as `http.StatusOK` directly in controller without importing `net/http`. + +[For Detail](https://github.com/goravel/framework/blob/v1.10.0/contracts/http/status.go) + +### APP_KEY required + +Version: v1.10.0 + +The `APP_KEY` in the `.env` file is changed to required, you can run command to generate the APP_KEY: `go run . artisan key:generate`. + +### Add ctx parameter to the methods under Form Request + +Version: v1.10.0 + +Add `ctx http.Context` parameter to the methods under Form Request: `Rules`, `Messages`, `Attributes`, `PrepareForValidation`, allows you to do more custom configurations. + +[For Detail](../the-basics/validation.md#creating-form-requests) + +### facades.Auth.Parse add payload returns + +Version: v1.10.0 + +`err := facades.Auth.Parse(ctx, token)` change to `payload, err := facades.Auth.Parse(ctx, token)`, through `payload` you can get: + +1. `Guard`: Current Guard; +2. `Key`: User flag; +3. `ExpireAt`: Expire time; +4. `IssuedAt`: Issued time; + +[For Detail](../security/authentication.md#parse-token) + +### Some methods of Orm add new return values + +Version: v1.10.0 + +The following methods add `*Result` return value to get the number of affected rows: + +```go +res, err := query.Delete(&user) +res, err := query.Exec(fmt.Sprintf("DELETE FROM users where id = %d", user.ID)) +res, err := query.ForceDelete(&User{}) +res, err := query.Updates(User{Avatar: "avatar"}) + +// Affected rows +num := res.RowsAffected +``` From 9a61b90b368bfb42413c8f2af0564e0b874e8550 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:55 +0800 Subject: [PATCH 054/163] New translations v1.11.md (Uzbek) [skip ci] Update translations (Uzbek) v1.11.md --- uz_UZ/upgrade/v1.11.md | 245 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 uz_UZ/upgrade/v1.11.md diff --git a/uz_UZ/upgrade/v1.11.md b/uz_UZ/upgrade/v1.11.md new file mode 100644 index 000000000..83651b8c3 --- /dev/null +++ b/uz_UZ/upgrade/v1.11.md @@ -0,0 +1,245 @@ +# Upgrading To v1.11 From v1.10 + +[[toc]] + +## v1.11.3 + +### Bug Fixes 🐛 + +- [The problem of process interruption caused by panic in Schedule](#the-problem-of-process-interruption-caused-by-panic-in-schedule) +- [The problem that DailyAt in Schedule will be executed every minute](#the-problem-that-dailyat-in-schedule-will-be-executed-every-minute) + +## v1.11.2 + +### Bug Fixes 🐛 + +- [Fix the data error of using Request.Input() and Request.Bind() at the same time](#fix-the-data-error-of-using-request-input\(\)-and-request-bind\(\)-at-the-same-time) + +## v1.11.1 + +### Exciting New Features 🎉 + +- [Route add resource routing](#route-add-resource-routing) +- [Request add new methods](#request-add-new-methods) +- [Storage add new methods](#storage-add-new-methods) +- [File add new methods](#file-add-new-methods) + +### Bug Fixes 🐛 + +- [Fix the error of incorrect windows path for Filesystem](#fix-the-error-of-incorrect-windows-path-for-filesystem) +- [Fix the panic of the Header method for Request](#fix-the-panic-of-the-header-method-for-request) + +## v1.11.0 + +## Exciting New Features 🎉 + +- [Orm add model events(1.11.0)](#orm-add-model-events) + +## Enhancements 🚀 + +- [Cache add and optimize methods(1.11.0)](#cache-add-and-optimize-methods) +- [Route supports Fallback route(1.11.0)](#route-supports-fallback-route) +- [Orm adds new methods(1.11.0)](#orm-adds-new-methods) +- [Optimize facades.Config.Add()(1.11.0)](#optimize-facades-config-add) +- [Change Sqlite driver(1.11.0)](#change-sqlite-driver) +- [contracts/http add method mapping of net/http(1.11.0)](#contracts-http-add-method-mapping-of-net-http) + +### Breaking Changes 🛠 + +- [Orm removes methods(1.11.0)](#_2-remove-deprecated-methods) + +### Bug Fixes 🐛 + +- The problem that the hashing configuration does not take effect under some situations(1.11.0) +- Non-thread safety problems in RateLimiter(1.11.0) + +## Upgrade Guide + +Please upgrade the framework step by step according to the content in this section. + +**Estimated Upgrade Time: 1 Minutes** + +### 1. Updating Dependencies + +Update dependencies in the `go.mod` file: + +``` +go get -u github.com/goravel/framework@v1.11.0 && go mod tidy +``` + +### 2. Remove deprecated methods + +``` +import ( + "github.com/goravel/framework/database" + "github.com/goravel/framework/database/gorm" +) + +// Deprecated +database.NewGormInstance() +// Replace with(Note: This method is not recommended, please try not to use it) +gorm.New() + +// Deprecated +facades.Orm.Query().Updates() +// Replace with(Only modify the method name is fine, no need to modify the parameters) +facades.Orm.Query().Update() + +// The Update method changes return value +// Before +err := facades.Orm.Query().Update() +// After +res, err := facades.Orm.Query().Update() +``` + +## New Content + +This section does not involve code changes, only enhancements. + +### Orm add model events + +Version: v1.11.1 + +Orm models dispatch several events, allowing you to hook into the following moments in a model's lifecycle: `Retrieved`, `Creating`, `Created`, `Updating`, `Updated`, `Saving`, `Saved`, `Deleting`, `Deleted`, `ForceDeleting`, `ForceDeleted`. + +[For Detail](../orm/getting-started.md#events) + +### Cache add and optimize methods + +Version: v1.11.1 + +#### New Methods + +| Methods | Action | +| --------- | --------------------------------------------------------------------------------------------- | +| Decrement | [Decrement](../digging-deeper/cache.md#incrementing--decrementing-values) | +| Increment | [Increment](../digging-deeper/cache.md#incrementing--decrementing-values) | +| Lock | [Atomic Locks](../digging-deeper/cache.md#atomic-locks) | +| Store | [Accessing Multiple Cache Stores](../digging-deeper/cache.md#accessing-multiple-cache-stores) | + +#### Optimize methods + +`Get`, `GetBool`, `GetInt`, `GetInt64`, `GetString`, `Pull` no longer need to pass a default value(Backwards compatible). + +### Route supports Fallback route + +Version: v1.11.1 + +You may define a route that will be executed when no other route matches the incoming request. + +```go +facades.Route.Fallback(func(ctx http.Context) http.Response { + return ctx.Response().String(404, "not found") +}) +``` + +### Orm adds new methods + +Version: v1.11.1 + +| Method | Action | +| ---------------------- | -------------------------------------------------------------------- | +| db.Raw | [Raw Expressions](../orm/getting-started.md#raw-expressions) | +| LockForUpdate | [Pessimistic Locking](../orm/getting-started.md#pessimistic-locking) | +| SharedLock | [Pessimistic Locking](../orm/getting-started.md#pessimistic-locking) | + +### Optimize facades.Config.Add() + +Version: v1.11.0 + +The `configuration` parameter of `facades.Config.Add()` changes to `any` from `map[string]any`, make configuration more flexible. + +[For Detail](../getting-started/configuration.md#set-configuration) + +### Change Sqlite driver + +Because `github.com/mattn/go-sqlite3` requires `CGO` to be started, so replacing a third-party package that does not require `CGO`: `github.com/glebarez/go-sqlite`. + +### contracts/http add method mapping of net/http + +Version: v1.11.0 + +You can use `http.MethodGet` in controller directly, instead of import `net/http`. + +[For Detail](https://github.com/goravel/framework/blob/v1.11.0/contracts/http/method.go) + +### Route Add Resource Routing + +Version: v1.11.1 + +```go +facades.Route.Resource("/resource", resourceController) +``` + +[For Detail](../the-basics/routing.md#resource-routing) + +### Request Add New Methods + +Version: v1.11.1 + +| Method | Action | +| ------- | --------------------------------------------------------------------------------------------------------- | +| All | [Retrieving all input data](../the-basics/request.md#retrieving-all-input-data) | +| Host | [Retrieving the request HOST](../the-basics/request.md#retrieving-the-request-host) | +| Queries | [Retrieving input from the query string](../the-basics/request.md#retrieving-input-from-the-query-string) | + +About to be deprecated the `Form`, `Json` methods, please use `Input` instead. + +### Storage Add New Methods + +Version: v1.11.1 + +| Method | Action | +| ------------ | ----------------------------------------------------------------------------------- | +| LastModified | [Get the last modified time of file](../digging-deeper/filesystem.md#file-metadata) | +| MimeType | [Get the mime type of file](../digging-deeper/filesystem.md#file-metadata) | + +### File Add New Methods + +Version: v1.11.1 + +| Method | Action | +| ------------ | ----------------------------------------------------------------------------------- | +| LastModified | [Get the last modified time of file](../digging-deeper/filesystem.md#file-metadata) | +| MimeType | [Get the mime type of file](../digging-deeper/filesystem.md#file-metadata) | +| Size | [Get the size of file](../digging-deeper/filesystem.md#file-metadata) | + +### Fix The Error Of Incorrect Windows Path For Filesystem + +Version: v1.11.1 + +There is a wrong slash in windows system. + +### Fix The Panic Of The Header Method For Request + +Version: v1.11.1 + +`ctx.Request().Header( key: "token")` will panic. + +### Fix The Data Error Of Using Request.Input() And Request.Bind() At The Same Time + +Version: v1.11.2 + +`Request.Input()` will clear `Request.Body`, if you use `Request.Bind()` after that, you will not be able to get the data correctly. + +### The problem of process interruption caused by panic in Schedule + +Version: v1.11.3 + +The Schedule process will interruption when occurring panic, all tasks wil lbe affected. + +### The problem that DailyAt in Schedule will be executed every minute + +Version: v1.11.3 + +Fix the problem that `DailyAt` will be executed every minute: + +```go +func (kernel *Kernel) Schedule() []schedule.Event { + return []schedule.Event{ + facades.Schedule.Call(func() { + fmt.Print("1") + }).DailyAt("18:00"), + } +} +``` From 1ecc4574fd5327b37258c3ffba0721ec36940f8a Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:56 +0800 Subject: [PATCH 055/163] New translations v1.12.md (Uzbek) [skip ci] Update translations (Uzbek) v1.12.md --- uz_UZ/upgrade/v1.12.md | 329 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 329 insertions(+) create mode 100644 uz_UZ/upgrade/v1.12.md diff --git a/uz_UZ/upgrade/v1.12.md b/uz_UZ/upgrade/v1.12.md new file mode 100644 index 000000000..459327662 --- /dev/null +++ b/uz_UZ/upgrade/v1.12.md @@ -0,0 +1,329 @@ +# Upgrading To v1.12 From v1.11 + +## v1.12.6 + +### Bug Fixes 🐛 + +- [Fix The Problem Of JWT](#fix-the-problem-of-jwt) + +## v1.12.5 + +### Bug Fixes 🐛 + +- [Fix The Problem Of facades.Orm().Query().Load()](#fix-the-problem-of-facades-orm-query-load) + +## v1.12.4 + +### Bug Fixes 🐛 + +- [The Problem Of The Throttle Middleware Throw Panic](#the-problem-of-the-throttle-middleware-throw-panic) + +## v1.12.3 + +### Bug Fixes 🐛 + +- [The Problem Of make:package Command Under Windows](#the-problem-of-make-package-command-under-windows) + +## v1.12.2 + +### Bug Fixes 🐛 + +- [The Problem Of facades.Gate() Return nil](#the-problem-of-facades-gate-return-nil) + +## v1.12.1 + +### Bug Fixes 🐛 + +- [The Panic Problem Caused By File Path Under Windows](#the-panic-problem-caused-by-file-path-under-windows) + +## v1.12.0 + +### Exciting New Features 🎉 + +- [Service Container(1.12.0)](#service-container) +- [Package Development(1.12.0)](#package-development) +- [Add Carbon Module](#add-helpers-methods) + +## Enhancements 🚀 + +- [Artisan Flag Adds New Methods](#artisan-flag-adds-new-methods) +- [Add Helpers Methods](#add-helpers-methods) +- [Upgrade Dependencies](#upgrade-dependencies) +- [Migration Adds New Methods](#migration-adds-new-methods) +- [Some `make` Commands Support Subdirectories](#some-make-commands-support-subdirectories) + +## Breaking Changes 🛠 + +- [Modify The Calling Type Of Facades(1.12.0)](#_3-modify-facades) +- [Optimize Artisan Flag(1.12.0)](#_6-modify-flag-in-the-artisan-command-if-using) +- [Filesystem Module Cancels Default Support For S3, OSS, COS, Minio](#_7-filesystem-module-cancels-default-support-for-s3-oss-cos-minio) +- [Cache Module Cancels Default Support For Redis](#_8-cache-module-cancels-default-support-for-redis) +- [Change The Type Of CreatedAt, UpdatedAt In Model](#_9-change-the-type-of-createdat-updatedat-in-model) +- [Optimize The Rule Of Validation Module](#_10-optimize-the-rule-of-validation-module) + +## Upgrade Guide + +Please upgrade the framework step by step according to the content in this section. + +**Estimated Upgrade Time: 30 Minutes** + +### 1. Updating Dependencies + +Update dependencies in the `go.mod` file: + +``` +go get -u github.com/goravel/framework@v1.12.0 && go mod tidy +``` + +There is an error after running `go mod tidy`, the error will be solved after performing the following upgrade steps. + +### 2. Modify `bootstrap/app.go` + +```go +// Before +app := foundation.Application{} + +// After +app := foundation.NewApplication() +``` + +### 3. Modify facades.\* + +| Before | After | +| --------------------- | ----------------------- | +| `facades.Artisan` | `facades.Artisan()` | +| `facades.Auth` | `facades.Auth()` | +| `facades.Cache` | `facades.Cache()` | +| `facades.Config` | `facades.Config()` | +| `facades.Crypt` | `facades.Crypt()` | +| `facades.Event` | `facades.Event()` | +| `facades.Gate` | `facades.Gate()` | +| `facades.Grpc` | `facades.Grpc()` | +| `facades.Hash` | `facades.Hash()` | +| `facades.Log` | `facades.Log()` | +| `facades.Mail` | `facades.Mail()` | +| `facades.Orm` | `facades.Orm()` | +| `facades.Queue` | `facades.Queue()` | +| `facades.RateLimiter` | `facades.RateLimiter()` | +| `facades.Route` | `facades.Route()` | +| `facades.Schedule` | `facades.Schedule()` | +| `facades.Storage` | `facades.Storage()` | +| `facades.Validation` | `facades.Validation()` | + +### 4. Modify `app/providers/*` + +Add import for all files: + +```go +import ( + "github.com/goravel/framework/contracts/foundation" +) +``` + +All of `Register`, `Boot` methods Add `app foundation.Application` input parameter: + +```go +func (receiver *AppServiceProvider) Register(app foundation.Application) {} + +func (receiver *AppServiceProvider) Boot(app foundation.Application) {} +``` + +### 5. Modify `app/config/app.go` + +Modify import: + +```go +// Before +"github.com/goravel/framework/contracts" + +"providers": []contracts.ServiceProvider{ + +// After +"github.com/goravel/framework/contracts/foundation" + +"providers": []foundation.ServiceProvider{ +``` + +### 6. Modify Flag in the Artisan command(If using) + +The items in the `[]command.Flag` add `&command.StringFlag` type: + +```go +// Before +func (receiver *VendorPublishCommand) Extend() command.Extend { + return command.Extend{ + Category: "test", + Flags: []command.Flag{ + { + Name: "test", + }, + }, + } +} + +// After +func (receiver *VendorPublishCommand) Extend() command.Extend { + return command.Extend{ + Category: "test", + Flags: []command.Flag{ + &command.StringFlag{ + Name: "test", + }, + }, + } +} +``` + +### 7. Filesystem Module Cancels Default Support For S3, OSS, COS, Minio + +In order to reduce the loading of unnecessary third packages, reduce package volume, and improve compilation efficiency, Goravel will gradually strip each module driver into an independent expansion packages. In this upgrade, the `Filesystem` module cancels the default support for `S3`, `OSS`, `COS`, `Minio` drivers, and transfers support to independent extension packages. + +Removes keys in `config/filesystems.go::disks` except `local` and drivers which are using: + +```go +// Modified +"disks": map[string]any{ + "local": map[string]any{ + "driver": "local", + "root": "storage/app", + "url": config.Env("APP_URL", "").(string) + "/storage", + }, +}, +``` + +If you are using other drivers expect `local`, please refer to the corresponding driver documentation for installation: + +| Driver | Link | +| ------ | ---------------------------------------------------------------------------------------------------- | +| S3 | [https://github.com/goravel/s3](https://github.com/goravel/s3) | +| OSS | [https://github.com/goravel/oss](https://github.com/goravel/oss) | +| COS | [https://github.com/goravel/cos](https://github.com/goravel/cos) | +| Minio | [https://github.com/goravel/minio](https://github.com/goravel/minio) | + +### 8. Cache Module Cancels Default Support For Redis + +Remove the `redis` key in `config/cache.go::stores` if you are not using it: + +```go +// Modified +"stores": map[string]any{ + "memory": map[string]any{ + "driver": "memory", + }, +}, +``` + +If you are using the `redis` driver, please refer to the `redis` driver documentation for installation: + +| Driver | Link | +| ------ | ---------------------------------------------------------------------------------------------------- | +| Redis | [https://github.com/goravel/redis](https://github.com/goravel/redis) | + +### 9. Change The Type Of CreatedAt, UpdatedAt In Model(If using) + +In order to make the time type more standard in API output, the type of `CreatedAt`, `UpdatedAt` in `Model` change to `carbon.DateTime` from `time.Time`. If you have additional processing for these two fields, you can get the original `time.Time` type through the `CreatedAt.ToStdTime()` method. + +### 10. Optimize The Rule Of Validation Module(If using) + +Check the zero value in the original validate rule, for example, if the rule is set to `date` and `required` is not set, and the field is empty or not passed, the validation module will prompt that field is required. After optimization, the validation module will passed the check, which is more intuitive to use. If you are using relevant validation, please ensure that the upgrade is as expected. + +### 11. Install dependencies again + +Run `go mod tidy` + +## Function Introduction + +### Service Container + +Version: v1.12.0 + +All services in Goravel are registered in the service container, providing strong support for the package development, [For Detail](../architecture-concepts/service-container.md) + +### Package Development + +Version: v1.12.0 + +Packages are the primary way of adding functionality to Goravel, can enrich the ecology of Goravel, [For Detail](../digging-deeper/package-development.md) + +### Artisan Flag Adds New Methods + +Version: v1.12.0 + +Add methods for Artisan module to get different types of `Flag`, [For Detail](../digging-deeper/artisan-console.md#options) + +### Add Helpers Methods + +Version: v1.12.0 + +Add `path` and `carbon` Helpers methods, you can easily get the path information and deal with time in project, [For Detail](../digging-deeper/helpers.md)。 + +### Upgrade Dependencies + +Version: v1.12.0 + +To provide better feature support, the versions of all packages that Goravel depends on have been upgraded. + +### Migration Adds New Methods + +Version: v1.12.0 + +| Commands | Action | +| ------------------------------- | ----------------------------------------- | +| migrate:fresh | Drop all tables and re-run all migrations | +| migrate:refresh | Reset and re-run all migrations | +| migrate:reset | Rollback all database migrations | +| migrate:status | Show the status of each migration | + +### Some `make` Commands Support Subdirectories + +Version: v1.12.0 + +| 命令 | 生成文件 | +| --------------------------------------------------- | --------------------------------------------------------------------------------- | +| make:policy User/AuthPolicy | app/policies/User/auth_policy.go | +| make:command Goravel/CleanCache | app/console/commands/Goravel/clean_cache.go | +| make:model User/Phone | app/models/User/phone.go | +| make:observer User/PhoneObserver | app/observers/User/phone_observer.go | +| make:event User/GoravelEvent | app/events/User/goravel_event.go | +| make:listener User/GoravelListen | app/listeners/User/goravel_listen.go | +| make:controller User/AuthController | app/http/controllers/User/auth_controller.go | +| make:middleware User/Auth | app/http/middleware/User/auth.go | +| make:request User/Auth | app/http/requests/User/auth.go | +| make:job Goravel/Job | app/jobs/Goravel/job.go | +| make:rule User/Phone | app/rules/User/phone.go | + +### The Panic Problem Caused By File Path Under Windows + +Version: v1.12.1 + +Fix the panic problem caused by backslash when the `make` command automatically creates folders under Windows. + +### The Problem Of facades.Gate() Return nil + +Version: v1.12.2 + +Fix the problem of `facades.Gate()` return nil. + +### The Problem Of make:package Command Under Windows + +Version: v1.12.3 + +The file created by the `make:package` command has a wrong path under Windows. + +### The Problem Of The Throttle Middleware Throw Panic + +Version: v1.12.4 + +Fix the problem of the throttle middleware throw panic. + +### Fix The Problem Of facades.Orm().Query().Load() + +Version: v1.12.5 + +Fix the problem that `facades.Orm().Query().Load()` cannot load the model correctly in some cases. + +### Fix The Problem Of JWT + +Version: v1.12.6 + +Fix the problem that when the JWT Token is expired and invalid, the expiration error is returned, and the invalid error is expected to be returned first. From 6c08b32d3cf6f4e3d18ec4ca8b5ba018b296e133 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:58 +0800 Subject: [PATCH 056/163] New translations v1.13.md (Uzbek) [skip ci] Update translations (Uzbek) v1.13.md --- uz_UZ/upgrade/v1.13.md | 509 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 509 insertions(+) create mode 100644 uz_UZ/upgrade/v1.13.md diff --git a/uz_UZ/upgrade/v1.13.md b/uz_UZ/upgrade/v1.13.md new file mode 100644 index 000000000..3ac5a1f82 --- /dev/null +++ b/uz_UZ/upgrade/v1.13.md @@ -0,0 +1,509 @@ +# Upgrading To v1.13 From v1.12 + +### Exciting New Features 🎉 + +- [Seeding](#seeding) +- [Factories](#factories) +- [Testing](#testing) +- [Views](#views) + +## Enhancements 🚀 + +- [Upgrade The Default Version Of Golang To 1.20](#upgrade-the-default-version-of-golang-to-1-20) +- [Task Scheduling Supports Scale Horizontally](#task-scheduling-supports-scale-horizontally) +- [Add Debug Methods](#add-debug-methods) +- [make:controller Command Adds Parameter](#make-controller-command-adds-parameter) +- [Add Status Method For Response](#add-status-method-for-response) +- [Add Sum and Cursor Methods For Orm](#add-sum-and-cursor-methods-for-orm) +- [The Route Module Supports Configure Driver](#the-route-module-supports-configure-driver) +- [Add InputArray And InputMap Methods For Request](#add-inputarray-and-inputmap-methods-for-request) +- [The Model Of Orm Supports Custom Connection](#the-model-of-orm-supports-custom-connection) +- [Add Cloudinary Driver For Filesystem](#add-cloudinary-driver-for-filesystem) +- [Add New Chain Methods For Log](#add-new-chain-methods-for-log) + +### v1.13.4 + +- [The Service Startup Supports Environment Variables](#the-service-startup-supports-environment-variables) + +## Breaking Changes 🛠 + +- [Remove The Global HTTP Middleware Loaded By Default](#_5-remove-the-global-http-middleware-loaded-by-default) +- [Optimize The Return of Controller](#_6-optimize-the-return-of-controller) +- [Change The Parameter Of The Group Method In facades.Route()](#_7-change-the-parameter-of-the-group-method-in-facades-route) +- [Optimize Remember And RememberForever Methods In facades.Cache()(If using)](#_8-optimize-remember-and-rememberforever-methods-in-facades-cache-if-using) +- [Change The Package Name Of access.NewAllowResponse and access.NewDenyResponse(If using)](#_9-change-the-package-name-of-access-newallowresponse-and-access-newdenyresponse-if-using) +- [Remove Deprecated Methods(If using)](#_10-remove-deprecated-methods-if-using) + +### Bug Fixes 🐛 + +- [Fix facades.Auth().User()](#fix-facades-auth-user) +- [Fix Custom .env Path Does Not Take Effect In Some Cases](#fix-custom-env-path-does-not-take-effect-in-some-cases) +- [Fix Token Expires Immediately When ttl == 0 Is Set In JWT](#fix-token-expires-immediately-when-ttl-0-is-set-in-jwt) + +#### v1.13.2 + +- [Fix facades.Storage().Url() Returns Wrong Path Under Windows](#fix-facades-storage-url-returns-wrong-path-under-windows) +- [Fix Abnormal Connection When The Postgres Password Is Empty](#fix-abnormal-connection-when-the-postgres-password-is-empty) +- [Fix The With Method Is Invalid When Using The Cursor Method Of Orm](#fix-the-with-method-is-invalid-when-using-the-cursor-method-of-orm) + +#### v1.13.4 + +- [Fix The Validation Module Cant Verify The Route Params](#fix-the-validation-module-cant-verify-the-route-params) +- [Fix The Fiber Driver Cant Return File](#fix-the-fiber-driver-cant-return-file) +- [Fix The Global Middleware Of Fiber Driver Panic](#fix-the-global-middleware-of-fiber-driver-panic) +- [Fix The ContentType Setting of Fiber Driver Is Different From Gin Driver](#fix-the-contenttype-setting-of-fiber-driver-is-different-from-gin-driver) + +#### v1.13.5 + +- [Fix The Connection Of Model Does Not Work](#fix-the-connection-of-model-does-not-work) +- [Fix The Error Of Mock Log](#fix-the-error-of-mock-log) + +#### v1.13.6 v1.13.7 + +- [Fix The Problem Of Nonlinear Execution Of Query Chain](#fix-the-problem-of-nonlinear-execution-of-query-chain) + +#### v1.13.8 + +- [Fix The Problem Of facades.Auth().Parse()](#fix-the-problem-of-facades-auth-parse) +- [Fix The Problem of facades.Orm().WithContext()](#fix-the-problem-of-facades-orm-withcontext) +- [The Queue Log Is Controlled By APP_DEBUG](#the-queue-log-is-controlled-by-app-debug) + +#### v1.13.9 + +- [Fix The Problem Of The New Line Print Of Log Is Incorrect](#fix-the-problem-of-the-new-line-print-of-log-is-incorrect) +- [Fix The Problem Of The vendor:publish Commabnd Can Not Publish Directory](#fix-the-problem-of-the-vendor-publish-commabnd-can-not-publish-directory) + +### v1.13.10 + +- [Fix The Traces Do Not Cleaned When Calling Log.Info After Log.Error](#fix-the-traces-do-not-cleaned-when-calling-log-info-after-log-error) +- [Fix The GetAttribute Of Orm Event Returns Error Data](#fix-the-getattribute-of-orm-event-returns-error-data) +- [Add ToSql, ToRawSql Methods For ORM](#add-tosql-torawsql-methods-for-orm) + +## Upgrade Guide + +Please upgrade the framework step by step according to the content in this section. + +**Estimated Upgrade Time: 10 Minutes** + +### 1. Updating Dependencies + +Update dependencies in the `go.mod` file: + +``` +go get -u github.com/goravel/framework@v1.13.9 && go get -u github.com/goravel/gin +``` + +### 2. Add New Files + +[tests](https://github.com/goravel/goravel/tree/v1.13.x/tests) + +[database/seeders/database_seeder.go](https://github.com/goravel/goravel/tree/v1.13.x/database/seeders/database_seeder.go) + +[app/providers/database_service_provider.go](https://github.com/goravel/goravel/tree/v1.13.x/app/providers/database_service_provider.go) + +### 3. Register New Providers + +Note the order: + +```go +import ( + "github.com/goravel/framework/testing" + "github.com/goravel/gin" +) + +// config/app.go +"providers": []foundation.ServiceProvider{ + ... + &validation.ServiceProvider{}, + // New + &testing.ServiceProvider{}, + &providers.AppServiceProvider{}, + ... + &providers.ValidationServiceProvider{}, + // New + &providers.DatabaseServiceProvider{}, + // New + &gin.ServiceProvider{}, +} +``` + +### 4. Add Configuration + +Modify [config/http.go](https://github.com/goravel/goravel/tree/v1.13.x/config/http.go) + +```go +import ( + "github.com/goravel/framework/contracts/route" + "github.com/goravel/framework/facades" + ginfacades "github.com/goravel/gin/facades" +) + +config.Add("http", map[string]any{ + // HTTP Driver + "default": "gin", + // HTTP Drivers + "drivers": map[string]any{ + "gin": map[string]any{ + "route": func() (route.Route, error) { + return ginfacades.Route("gin"), nil + }, + }, + }, + ... +} +``` + +Modify [config/cors.go](https://github.com/goravel/goravel/tree/v1.13.x/config/cors.go) + +```go +config.Add("cors", map[string]any{ + ... + // New + "paths": []string{"*"}, + "allowed_methods": []string{"*"}, + ... +} +``` + +### 5. Remove The Global HTTP Middleware Loaded By Default + +1. The `tls` and `cors` middleware have been integrated into the default HTTP driver, therefore, `middleware.Cors()` and `middleware.Tls()` in the `app/http/kernel.go` file need to be removed. + +2. The `facades.Route().GlobalMiddleware(http.Kernel{}.Middleware()...)` method in the `app/providers/route_service_provider.go` file moves to `Boot` from `Register`: + +```go +package providers + +... + +type RouteServiceProvider struct { +} + +func (receiver *RouteServiceProvider) Register(app foundation.Application) { +} + +func (receiver *RouteServiceProvider) Boot(app foundation.Application) { + //Add HTTP middleware + facades.Route().GlobalMiddleware(http.Kernel{}.Middleware()...) + + receiver.configureRateLimiting() + + routes.Web() +} + +func (receiver *RouteServiceProvider) configureRateLimiting() { + +} +``` + +### 6. Optimize The Return of Controller + +`Controller` adds return value `http.Response`, `ctx.Response()` can be return directly, there is no need to use `return` separately to make the logic smoother. + +```go +// Before +func (r *UserController) Show(ctx http.Context) { + ctx.Response().Success().Json(http.Json{ + "Hello": "Goravel", + }) + return +} + +// After +func (r *UserController) Show(ctx http.Context) http.Response { + return ctx.Response().Success().Json(http.Json{ + "Hello": "Goravel", + }) +} +``` + +### 7. Change The Parameter Of The Group Method In facades.Route() + +Change `route.Route` to `route.Router`: + +```go +// Before +facades.Route().Group(func(route route.Route) + +// After +facades.Route().Group(func(route route.Router) +``` + +### 8. Optimize Remember And RememberForever Methods In facades.Cache()(If using) + +The type of `callback` changes to `func() (any, error)` from `func() any`: + +```go +// Before +Remember(key string, ttl time.Duration, callback func() any) (any, error) +RememberForever(key string, callback func() any) (any, error) + +// After +Remember(key string, ttl time.Duration, callback func() (any, error)) (any, error) +RememberForever(key string, callback func() (any, error)) (any, error) +``` + +### 9. Change The Package Name Of access.NewAllowResponse and access.NewDenyResponse(If using) + +Change `/contracts/auth/access` to `/auth/access`: + +```go +// Before +import "github.com/goravel/framework/contracts/auth/access" + +access.NewAllowResponse() +access.NewDenyResponse() + +// After +import "github.com/goravel/framework/auth/access" + +access.NewAllowResponse() +access.NewDenyResponse() +``` + +### 10. Remove Deprecated Methods(If using) + +1. Remove `ctx.Request().Form()` and `ctx.Request().Json()` methods, use the `ctx.Request().Input()` method instead; + +2. Remove `GetLevel`, `GetTime`, `GetMessage` methods of `Log` custom driver, use `Level`, `Time`, `Message` methods instead; + +3. Remove the `gorm.New` method, the method is used to obtain the `gorm` instance directly, it is no longer recommended. if necessary, use the `gorm.NewGormImpl` method instead; + +## Function Introduction + +### Seeding + +Version: v1.13.1 + +[For Detail](../database/seeding.md) + +### Factories + +Version: v1.13.1 + +[For Detail](../orm/factories.md) + +### Testing + +Version: v1.13.1 + +[For Detail](../testing/getting-started.md) + +### Views + +Version: v1.13.1 + +[For Detail](../the-basics/views.md) + +### Upgrade The Default Version Of Golang To 1.20 + +Version: v1.13.1 + +Golang 1.18 and 1.19 have been discontinued and the framework has been upgraded to 1.20 accordingly, [for detail](https://endoflife.date/go). If you want to continue using 1.18 or 1.19, just modify the version number in `go.mod`, they are fully compatible at present. + +### Task Scheduling Supports Scale Horizontally + +Version: v1.13.1 + +[For Detail](../digging-deeper/task-scheduling.md#running-tasks-on-one-server) + +### Add debug Methods + +Version: v1.13.1 + +[For Detail](../digging-deeper/helpers.md#debug) + +### make:controller Command Adds Parameter + +Version: v1.13.1 + +The `make:controller` command adds `--resource` parameter, the CURD struct can be created easily: + +``` +go run . artisan make:controller --resource UserController +``` + +### Add Status method for Response + +Version: v1.13.1 + +[For Detail](../the-basics/response.md#custom-code) + +### Add Sum and Cursor methods for Orm + +Version: v1.13.1 + +[For Detail](../orm/getting-started.md#facades-orm-query-facades-orm-transaction-available-functions) + +### The Route Module Supports Configure Driver + +Version: v1.13.1 + +Separate the original default driver Gin of the Route module into a package, it can be injected into Goravel by configuration. after this optimization, providers a convenient channel for injecting other HTTP packages into Goravel, currently two HTTP packages are officially supported: + +| Driver | Link | +| ------ | ---------------------------------------------------------------------------------------------------- | +| Gin | [https://github.com/goravel/gin](https://github.com/goravel/gin) | +| Fiber | [https://github.com/goravel/fiber](https://github.com/goravel/fiber) | + +### Add InputArray And InputMap Methods For Request + +Version: v1.13.1 + +[For Detail](../the-basics/request.md#retrieving-an-input-value) + +### The Model Of Orm Supports Custom Connection + +Version: v1.13.1 + +[For Detail](../orm/getting-started.md#database-connections) + +### Add Cloudinary Driver For Filesystem + +Version: v1.13.1 + +[For Detail](https://github.com/goravel/cloudinary) + +### Add New Chain Methods For Log + +Version: v1.13.1 + +[For Detail](../the-basics/logging.md#chain-methods) + +### Fix facades.Auth().User() + +Version: v1.13.1 + +1. Fix the problem that no error throws if the user didn't exist when using the `facades.Auth().User(ctx, &user)` method. + +2. Fix the problem that `user` can be found when the primary key isn't `int`; + +### Fix Custom .env Path Does Not Take Effect In Some Cases + +Version: v1.13.1 + +Fix the problem that custom .env path does not take effect in some cases. + +### Fix Token Expires Immediately When ttl == 0 Is Set In JWT + +Version: v1.13.1 + +Expect the token to never expire when `ttl == 0`. + +### Fix facades.Storage().Url() Returns Wrong Path Under Windows + +Version: v1.13.2 + +[Issue #263](https://github.com/goravel/goravel/issues/263) + +### Fix Abnormal Connection When The Postgres Password Is Empty + +Version: v1.13.2 + +[Issue #270](https://github.com/goravel/goravel/issues/270) + +### Fix The With Method Is Invalid When Using The Cursor Method Of Orm + +Version: v1.13.2 + +[Issue #253](https://github.com/goravel/goravel/issues/253) + +### The Service Startup Supports Environment Variables + +Version: v1.13.4 + +[Issue #265](https://github.com/goravel/goravel/issues/265) + +### Fix The Validation Module Cant Verify The Route Params + +goravel/gin: v1.1.6 + +goravel/fiber: v1.1.11 + +[Issue #294](https://github.com/goravel/goravel/issues/294) + +### Fix The Fiber Driver Cant Return File + +goravel/fiber: v1.1.11 + +[Issue #299](https://github.com/goravel/goravel/issues/299) + +### Fix The Global Middleware Of Fiber Driver Panic + +goravel/fiber: v1.1.11 + +[Issue #300](https://github.com/goravel/goravel/issues/300) + +### Fix The ContentType Setting Of Fiber Driver Is Different From Gin Driver + +goravel/fiber: v1.1.11 + +[Issue #296](https://github.com/goravel/goravel/issues/296) + +### Fix The Connection Of Model Does Not Work + +goravel/framework: v1.13.5 + +[Issue #312](https://github.com/goravel/goravel/issues/312) + +### Fix The Error Of Mock Log + +goravel/framework: v1.13.5 + +[Issue #320](https://github.com/goravel/goravel/issues/320) + +### Fix The Problem Of Nonlinear Execution Of Query Chain + +goravel/framework: v1.13.6 v1.13.7 + +[Issue #341](https://github.com/goravel/goravel/issues/341) + +### Fix The Problem Of facades.Auth().Parse() + +goravel/framework: v1.13.8 + +[Issue #388](https://github.com/goravel/goravel/issues/388) + +### Fix The Problem of facades.Orm().WithContext() + +goravel/framework: v1.13.8 + +[Issue #390](https://github.com/goravel/goravel/issues/390) + +### The Queue Log Is Controlled By APP_DEBUG + +goravel/framework: v1.13.8 + +The `Debug` and `Info` levels will not be print when `APP_DEBUG=false` + +[Issue #389](https://github.com/goravel/goravel/issues/389) + +### Fix The Problem Of The New Line Print Of Log Is Incorrect + +goravel/framework: v1.13.9 + +[Issue #395](https://github.com/goravel/goravel/issues/395) + +### Fix The Problem Of The vendor:publish Commabnd Can Not Publish Directory + +goravel/framework: v1.13.9 + +[Issue #345](https://github.com/goravel/goravel/issues/345) + +### Fix The Traces Do Not Cleaned When Calling Log.Info After Log.Error + +goravel/framework: v1.13.10 + +[Issue #402](https://github.com/goravel/goravel/issues/402) + +### Fix The GetAttribute Of Orm Event Returns Error Data + +goravel/framework: v1.13.10 + +[Issue #405](https://github.com/goravel/goravel/issues/405) + +### Add ToSql, ToRawSql Methods For ORM + +goravel/framework: v1.13.10 + +[Issue #411](https://github.com/goravel/goravel/issues/411) From 236f20ce65080fa797126a22c2acc182f0800d87 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:12:59 +0800 Subject: [PATCH 057/163] New translations v1.14.md (Uzbek) [skip ci] Update translations (Uzbek) v1.14.md --- uz_UZ/upgrade/v1.14.md | 542 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 542 insertions(+) create mode 100644 uz_UZ/upgrade/v1.14.md diff --git a/uz_UZ/upgrade/v1.14.md b/uz_UZ/upgrade/v1.14.md new file mode 100644 index 000000000..b1945c461 --- /dev/null +++ b/uz_UZ/upgrade/v1.14.md @@ -0,0 +1,542 @@ +# Upgrading To v1.14 From v1.13 + +### Exciting New Features 🎉 + +- [Localization](#localization) +- [Installer](#installer) +- [Cookie](#cookie) +- [Session](#session) + +### Enhancements 🚀 + +- [Support for setting body_limit and header_limit in Gin and Fiber drivers](#support-for-setting-body-limit-and-header-limit-in-gin-and-fiber-drivers) +- [Log adds new methods](#log-adds-new-methods) +- [Orm adds new methods](#orm-adds-new-methods) +- [Console adds new methods](#console-adds-new-methods) +- [Response adds new methods](#response-adds-new-methods) +- [Add Build command](#add-build-command) +- [Add helper methods](#add-helper-methods) +- [Redis driver supports TLS](#redis-driver-supports-tls) + +### Breaking Changes 🛠 + +- [Validation will not bind data if validation fails](#validation-will-not-bind-data-if-validation-fails) +- [Add new methods and modify methods for Testing module](#add-new-methods-and-modify-methods-for-testing-module) +- [Optimize the Queue method of Mail](#optimize-the-queue-method-of-mail) +- [Optimize the setting method of the Auth module ctx](#optimize-the-setting-method-of-the-auth-module-ctx) +- [Optimize the way of mock facades](#optimize-the-way-of-mock-facades) +- [Framework Orm model adds json tag](#framework-orm-model-adds-json-tag) + +### v1.14.1 + +- [Fix the session is not set successfully in the gin driver](#fix-the-session-is-not-set-successfully-in-the-gin-driver) +- [Fix the language file cannot be read in the localization module](#fix-the-language-file-cannot-be-read-in-the-localization-module) + +### v1.14.2 + +- [Fix Validation verification of image and file failed](#fix-validation-verification-of-image-and-file-failed) +- [Fix the cookie Expires set by the goravel/gin driver is invalid](#fix-the-cookie-expires-set-by-the-goravel-gin-driver-is-invalid) + +### v1.14.3 + +Upgrade the related packages: goravel/gin: v1.2.2, goravel/fiber: v1.2.2 + +- [Fix Validation cannot bind slice](#fix-validation-cannot-bind-slice) +- [Validation supports bind carbon](#validation-supports-bind-carbon) + +### v1.14.4 + +Upgrade the related packages: goravel/gin: v1.2.3 + +- [Fix Session concurrent problem](#fix-session-concurrent-problem) +- [Fix Gin sets Session same_site invalid](#fix-gin-sets-session-same_site-invalid) + +### v1.14.5 + +Upgrade the related packages: goravel/gin: v1.2.4, goravel/fiber: v1.2.3 + +- [Add Shutdown method for Route](#add-shutdown-method-for-route) + +### v1.14.7 + +Upgrade the related packages: goravel/gin: v1.2.5, goravel/fiber: v1.2.4 + +- [Optimize the ctx.WithValue method of HTTP](#optimize-the-ctx-withvalue-method-of-http) + +### v1.14.8 + +- [Fix the problem of conflicting listener registration](#fix-the-problem-of-conflicting-listener-registration) + +### v1.14.9 + +- [Fix the problem of custom Log driver console repeatedly printing](#fix-the-problem-of-custom-log-driver-console-repeatedly-printing) +- [Fix the problem of data binding error when HTTP JSON Request contains multi-level structure](#fix-the-problem-of-data-binding-error-when-http-json-request-contains-multi-level-structure) + +## Upgrade Guide + +Goravel v1.14 is developed and tested based on Golang 1.21, and generally compatible with other lower Golang versions. Please upgrade the framework step by step according to the content in this section. + +**Estimated Upgrade Time: 10 Minutes** + +### 1. Updating Dependencies + +``` +go get -u github.com/goravel/framework@v1.14.7 + +// If using gin +go get -u github.com/goravel/gin@v1.2.5 + +// If using fiber +go get -u github.com/goravel/fiber@v1.2.4 + +// If using redis +go get -u github.com/goravel/redis@v1.2.1 + +// If using s3 +go get -u github.com/goravel/s3@v1.2.0 + +// If using oss +go get -u github.com/goravel/oss@v1.2.0 + +// If using cos +go get -u github.com/goravel/cos@v1.2.0 + +// If using minio +go get -u github.com/goravel/minio@v1.2.0 + +// If using cloudinay +go get -u github.com/goravel/cloudinary@v1.2.0 + +go mod tidy +``` + +### 2. Adding Configuration Items + +1. `config/app.go` adds localization module configuration items: + +```go +"locale": "en", +"fallback_locale": "en", +"providers": []foundation.ServiceProvider{ + ... + &session.ServiceProvider{}, + &translation.ServiceProvider{}, + ... +} +``` + +2. If you want to use the `session` feature, add the [config/session.go](https://github.com/goravel/goravel/blob/master/config/session.go) file; + +### 3) If using the Validation module + +Confirm whether you are still trying to read the binding value even if the data validation fails. If so, you need to optimize the logic, because the value is empty after the upgrade. See: [Validation will not bind data if validation fails](#validation-will-not-bind-data-if-validation-fails). + +### 4. If using the Testing module + +Check whether using the `Clear`, `Image` methods, if so, need to modify accordingly: [Add new methods and modify methods for Testing module](#add-new-methods-and-modify-methods-for-testing-module) + +### 5. if using the Mail module + +Check whether using the `Queue` method, if so, need to modify accordingly: [Optimize the Queue method of Mail](#optimize-the-queue-method-of-mail) + +### 6. If using the Auth module + +Need to modify accordingly: [Optimize the setting method of the Auth module ctx](#optimize-the-setting-method-of-the-auth-module-ctx) + +### 7. If using the mock facades + +Need to modify accordingly: [Optimize the way of mock facades](#optimize-the-way-of-mock-facades) + +### 8. If using the framework Orm model and returning data directly through the endpoint + +Need to modify accordingly: [Framework Orm model adds json tag](#framework-orm-model-adds-json-tag) + +## Feature Introduction + +### Localization + +Version: v1.14.0 + +[View Documentation](../digging-deeper/localization.md) + +### Installer + +Version: v1.14.0 + +The installer allows you to easily download and initialize a new Goravel project. + +[View Documentation](http://github.com/goravel/installer) + +### Cookie + +Version: v1.14.0 + +[View Request Documentation](../the-basics/request.md#cookie) + +[View Response Documentation](../the-basics/response.md#cookie) + +### Session + +Version: v1.14.0 + +[View Documentation](../the-basics/session.md) + +### Support for setting body_limit and header_limit in Gin and Fiber drivers + +Version: v1.14.0 + +HTTP drivers support setting body_limit to limit the body size, see: [goravel/gin](https://github.com/goravel/gin/blob/c9d7706a6a04c05c8c33af5c97877a1ad2ea6362/README.md?plain=1#L54) and [goravel/fiber](https://github.com/goravel/fiber/blob/aa63ab657cd2b371fcda4df0090a41226f6c0704/README.md?plain=1#L56). + +### Log adds new methods + +Version: v1.14.0 + +| Method | Descrpton | +| ----------- | -------------------------------------- | +| `Stack` | Use multiple channels at the same time | +| `Channel` | Specified a channel | +| `WithTrace` | Print trace | + +[View Documentation](../the-basics/logging.md#write-to-a-specific-channel) + +### Orm adds new methods + +Version: v1.14.0 + +Add `WhereIn`, `OrWhereIn`, `OrWhereNotIn`, `WhereNotIn`, `WhereBetween`, `WhereNotBetween`, `WhereNull`, `OrWhereNull`, `OrderByDesc`, `OrderBy`, `InRandomOrder`, `Exists` methods. + +### Console adds new methods + +Version: v1.14.0 + +[View Documentation](../digging-deeper/artisan-console.md#prompting-for-input) + +### Response adds new methods + +Version: v1.14.0 + +[View documentation](../the-basics/response.md#no-content) + +### Add Build command + +Version: v1.14.0 + +The Goravel project can be compiled with the following command: `go run . artisan build`. + +[View Documentation](../getting-started/compile.md#compile-command) + +### Add helper methods + +Version: v1.14.0 + +- [Str](../digging-deeper/strings.md) +- [Map](../digging-deeper/helpers.md#maps) +- [Color](../digging-deeper/color.md) +- [Convert](../digging-deeper/helpers.md#convert) +- [Collect](../digging-deeper/helpers.md#collect) + +### Redis driver supports TLS + +Version: v1.14.0 + +[View Documentation](https://github.com/goravel/redis) + +### Validation will not bind data if validation fails + +Version: v1.14.0 + +Previously, when calling the methods below, the `userRequest` still bound the value, even if an error was returned. After the upgrade, it will no longer bind. + +```go +var userRequest requests.UserRequest +errors, err := ctx.Request().ValidateRequest(&userRequest) + +// or +validator, err := validation.Make(***) +err = validator.Bind(&userRequest) +``` + +### Add new methods and modify methods for Testing module + +Version: v1.14.0 + +1. Add [Fresh](../testing/getting-started.md#refresh-database) method; +2. Modify `Clear` method to [Stop](../testing/getting-started.md#uninstall-image) method; +3. The `Image` method adds `ExposedPorts` variable and remove `Timeout` variable; + +```go +database, err := facades.Testing().Docker().Database() +database.Image(testingcontract.Image{ + Repository: "mysql", + Tag: "5.7", + Env: []string{ + "MYSQL_ROOT_PASSWORD=123123", + "MYSQL_DATABASE=goravel", + }, + -- Timeout: 1000, + ++ ExposedPorts: []string{"3306"}, +}) +``` + +### Optimize the Queue method of Mail + +Version: v1.14.0 + +The input parameter of the `Queue` method changes from `queue *mail.Queue` to `queue ...mail.Queue`. + +```diff +-- facades.Mail().Queue(nil) +++ facades.Mail().Queue() + +-- facades.Mail().Queue(&mail.Queue{}) +++ facades.Mail().Queue(mail.Queue{}) +``` + +### Optimize the setting method of the Auth module ctx + +Version: v1.14.0 + +Previously, when calling the `Parse`, `User`, `Login`, `LoginUsingID`, `Refresh`, `Logout` methods, you need to pass `ctx`. After the upgrade, you no longer need to pass `ctx`, you can directly set it in `facades.Auth(ctx)`. + +```diff +-- facades.Auth().Parse(ctx, token) +++ facades.Auth(ctx).Parse(token) + +-- facades.Auth().User(ctx, &user) +++ facades.Auth(ctx).User(&user) + +-- facades.Auth().Login(ctx, &user) +++ facades.Auth(ctx).Login(&user) + +-- facades.Auth().LoginUsingID(ctx, id) +++ facades.Auth(ctx).LoginUsingID(id) + +-- facades.Auth().Refresh(ctx) +++ facades.Auth(ctx).Refresh() + +-- facades.Auth().Logout(ctx) +++ facades.Auth(ctx).Logout() +``` + +### Optimize the way of mock facades + +Version: v1.14.0 + +```diff +import github.com/goravel/framework/testing/mock + +++ mockFactory := mock.Factory() + +-- app := mock.App() +++ app := mockFactory.App() + +-- artisan := mock.Artisan() +++ artisan := mockFactory.Artisan() + +-- auth := mock.Auth() +++ auth := mockFactory.Auth() + +-- artisan := mock.Artisan() +++ artisan := mockFactory.Artisan() + +-- cache, driver, lock := mock.Cache() +++ cache := mockFactory.Cache() +++ driver := mockFactory.CacheDriver() +++ lock := mockFactory.CacheLock() + +-- config := mock.Config() +++ config := mockFactory.Config() + +-- crypt := mock.Crypt() +++ crypt := mockFactory.Crypt() + +-- event, task := mock.Event() +++ event := mockFactory.Event() +++ event := mockFactory.EventTask() + +-- gate := mock.Gate() +++ gate := mockFactory.Gate() + +-- grpc := mock.Grpc() +++ grpc := mockFactory.Grpc() + +-- hash := mock.Hash() +++ hash := mockFactory.Hash() + +-- mock.Log() +++ mockFactory.Log() + +-- mail := mock.Mail() +++ mail := mockFactory.Mail() + +-- orm, query, transaction, association := mock.Orm() +++ orm := mockFactory.Orm() +++ query := mockFactory.OrmQuery() +++ transaction := mockFactory.OrmTransaction() +++ association := mockFactory.OrmAssociation() + +-- queue, task := mock.Queue() +++ queue := mockFactory.Queue() +++ task := mockFactory.QueueTask() + +-- rateLimiter := mock.RateLimiter() +++ rateLimiter := mockFactory.RateLimiter() + +-- storage, driver, file := mock.Storage() +++ storage := mockFactory.Storage() +++ driver := mockFactory.StorageDriver() +++ file := mockFactory.StorageFile() + +-- seeder := mock.Seeder() +++ seeder := mockFactory.Seeder() + +-- validation, validator, errors := mock.Validation() +++ validation := mockFactory.Validation() +++ validator := mockFactory.ValidationValidator() +++ errors := mockFactory.ValidationErrors() + +-- view := mock.View() +++ view := mockFactory.View() +``` + +### Framework Orm model adds json tag + +Version: v1.14.0 + +If you are using the framework's Orm model and returning data directly through the endpoint, you need to create a new model according to the old and replace the old, or frontend needs to modify the field name according to the json tag. + +```go +type Model struct { + -- ID uint `gorm:"primaryKey"` + ++ ID uint `gorm:"primaryKey" json:"id"` + Timestamps +} + +type SoftDeletes struct { + -- DeletedAt gorm.DeletedAt `gorm:"column:deleted_at"` + ++ DeletedAt gorm.DeletedAt `gorm:"column:deleted_at" json:"deleted_at"` +} + +type Timestamps struct { + -- CreatedAt carbon.DateTime `gorm:"autoCreateTime;column:created_at"` + -- UpdatedAt carbon.DateTime `gorm:"autoUpdateTime;column:updated_at"` + ++ CreatedAt carbon.DateTime `gorm:"autoCreateTime;column:created_at" json:"created_at"` + ++ UpdatedAt carbon.DateTime `gorm:"autoUpdateTime;column:updated_at" json:"updated_at"` +} +``` + +### Fix the session is not set successfully in the gin driver + +goravel/framework: v1.14.1 + +### Fix the language file cannot be read in the localization module + +goravel/framework: v1.14.1 + +### Fix Validation verification of image and file failed + +goravel/framework: v1.14.2 + +goravel/gin: v1.2.2 + +goravel/fiber: v1.2.2 + +[Issue #450](https://github.com/goravel/goravel/issues/450) + +### Fix the cookie Expires set by the goravel/gin driver is invalid + +goravel/gin: v1.2.2 + +### Fix Validation cannot bind slice + +goravel/framework: v1.14.3 + +```go +type User struct { + Tags []string `form:"tags" json:"tags"` +} +``` + +### Validation supports bind carbon + +goravel/framework: v1.14.3 + +```go +// Define carbon field +type User struct { + Date carbon.Carbon `form:"date" json:"date"` +} +var user requests.User + +// Use ValidateRequest bind data +errors, err := ctx.Request().ValidateRequest(&user) + +// or use Validate bind data +validator, err := ctx.Request().Validate(map[string]string{ + "date": "required|date", +}) +err := validator.Bind(&user) + +// get date time +user.Date.ToDateTimeString() +``` + +### Fix Session concurrent problem + +goravel/framework: v1.14.4 + +当 Session 并发过高时,可能会出现 Session 读写冲突的问题。 + +### Fix Gin sets Session same_site invalid + +goravel/gin: v1.2.3 + +[Issue #455](https://github.com/goravel/goravel/issues/455) + +### Add Shutdown method for Route + +goravel/framework: v1.14.5 + +goravel/gin: v1.2.4 + +goravel/fiber: v1.2.3 + +[查看文档](../the-basics/routing.md#close-http-https-server) + +### Optimize the ctx.WithValue method of HTTP + +goravel/framework: v1.14.7 + +goravel/gin: v1.2.5 + +goravel/fiber: v1.2.4 + +The `key` of the `ctx.WithValue` method is changed from only supporting the `string` type to supporting the `any` type. + +```go +ctx.WithValue("Hello", "world") +ctx.WithValue(1, "hi") + +var key struct{} +ctx.WithValue(key, "hola") +``` + +### Fix the problem of conflicting listener registration + +goravel/framework: v1.14.8 + +Multiple events use the same listener, a listener conflict will be prompted when registering. + +[Issue #523](https://github.com/goravel/goravel/issues/523) + +### Fix the problem of custom Log driver console repeatedly printing + +goravel/framework: v1.14.9 + +[Issue #531](https://github.com/goravel/goravel/issues/531) + +### Fix the problem of data binding error when HTTP JSON Request contains multi-level structure + +goravel/framework: v1.14.9 + +[Issue #533](https://github.com/goravel/goravel/issues/533) From 5c4a14787fbd0e7b3a23b981d18c9583c6b5441f Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:01 +0800 Subject: [PATCH 058/163] New translations v1.15.md (Uzbek) [skip ci] Update translations (Uzbek) v1.15.md --- uz_UZ/upgrade/v1.15.md | 849 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 849 insertions(+) create mode 100644 uz_UZ/upgrade/v1.15.md diff --git a/uz_UZ/upgrade/v1.15.md b/uz_UZ/upgrade/v1.15.md new file mode 100644 index 000000000..0f2080abf --- /dev/null +++ b/uz_UZ/upgrade/v1.15.md @@ -0,0 +1,849 @@ +# Upgrading To v1.15 From v1.14 + +## Exciting New Features 🎉 + +- [Migration supports using Go language migration](#migration-supports-using-go-language-migration) +- [Testing supports HTTP testing](#testing-supports-http-testing) + +## Enhancements 🚀 + +- [HTTP supports return Stream](#http-supports-return-stream) +- [HTTP supports setting timeout](#http-supports-setting-timeout) +- [HTTP supports setting custom recovery method](#http-supports-setting-custom-recovery-method) +- [Request supports configure Filter](#request-supports-configure-filter) +- [Request adds the BindQuery method](#request-adds-the-bindquery-method) +- [Validation supports Regex rules](#validation-supports-regex-rules) +- [Schedule supports control log output](#schedule-supports-control-log-output) +- [Schedule adds the Shutdown method](#schedule-adds-the-shutdown-method) +- [Mail supports Mailable template](#mail-supports-mailable-template) +- [The trace in error log output supports jumping](#the-trace-in-error-log-output-supports-jumping) +- [Log supports printing key-value pairs in Context](#log-supports-printing-key-value-pairs-in-context) +- [Support directly setting DSN to connect to the database](#support-directly-setting-dsn-to-connect-to-the-database) +- [The Create method of Orm supports using map to create](#the-create-method-of-orm-supports-using-map-to-create) +- [Orm adds configuration items](#orm-adds-configuration-items) +- [Orm adds Restore method](#orm-adds-restore-method) +- [Orm's Log integrated Log module](#orm-s-log-integrated-log-module) +- [Postgres and Sqlserver drivers support Schema](#postgres-and-sqlserver-drivers-support-schema) +- [Add about command](#add-about-command) +- [Add db:show command](#add-db-show-command) +- [Add db:table command](#add-db-table-command) +- [Optimize Artisan output style](#optimize-artisan-output-style) +- [Auth adds the Id method](#auth-adds-the-id-method) +- [Multiple Auth.Guard can set their own TTL](#multiple-auth-guard-can-set-their-own-ttl) + +## Breaking Changes 🛠 + +- [The name of Postgresql driver changes to Postgres](#the-name-of-postgresql-driver-changes-to-postgres) +- [Modify the Orm.Transaction method callback parameter type](#modify-the-orm-transaction-method-callback-parameter-type) +- [Optimize the Delete and ForceDelete methods of Orm](#optimize-the-delete-and-forcedelete-methods-of-orm) +- [Optimize the Decrement and Increment methods of Cache](#optimize-the-decrement-and-increment-methods-of-cache) +- [Optimize the Call method of Artisan](#optimize-the-call-method-of-artisan) +- [Rename the Clear method of Testing.Database to Shutdown](#rename-the-clear-method-of-testing-database-to-shutdown) +- [Optimize the Build method of Testing.Database](#optimize-the-build-method-of-testing-database) +- [Optimize the Request.Input\* method](#optimize-the-request-input-method) +- [Optimize the validation.PrepareForValidation method](#optimize-the-validation-prepareforvalidation-method) +- [Optimize the Worker method of the Queue module](#optimize-the-worker-method-of-the-queue-module) + +## v1.15.3 + +- [Go Migration supports Boolean field](#go-migration-supports-boolean-field) +- [Go Migration supports custom field](#go-migration-supports-custom-field) +- [Optimize Artisan log output rules](#optimize-artisan-log-output-rules) + +## v1.15.4 + +Upgrade the related packages: goravel/gin: v1.3.3, goravel/fiber: v1.3.3 + +- [Fix the problem that ctx is nil in PrepareForValidation](#fix-the-problem-that-ctx-is-nil-in-prepareforvalidation) +- [Fix the problem that the Orm WithContext method reports an error in Fiber driver under high concurrency](#fix-the-problem-that-the-orm-withcontext-method-reports-an-error-in-fiber-driver-under-high-concurrency) +- [Optimize the packaging volume](#optimize-the-packaging-volume) +- [Optimize the problem that the model ID is nested multiple times](#optimize-the-problem-that-the-model-id-is-nested-multiple-times) +- [Add artisan command alias](#add-artisan-command-alias) + +## v1.15.5 + +Upgrade the related packages: goravel/redis: v1.3.1, goravel/fiber: v1.3.4 + +- [Fix the problem that Throttle fails to store in Redis driver](#fix-the-problem-that-throttle-fails-to-store-in-redis-driver) +- [Fix the problem that Fallback fails to work in Fiber driver](#fix-the-problem-that-fallback-fails-to-work-in-fiber-driver) + +## v1.15.6 + +- [Fix the problem that the Orm WithContext method reports an error in concurrent execution](#fix-the-problem-that-the-orm-withcontext-method-reports-an-error-in-concurrent-execution) + +## v1.15.7 + +- [Upgrade Carbon](#upgrade-carbon) + +## v1.15.8 + +Upgrade the related packages: goravel/fiber: v1.3.6 + +- [Fix the problem that facades.Testing().Docker().Database() reports an error](#fix-the-problem-that-facades-testing-docker-database-reports-an-error) +- [Fix the problem that the ctx.Request().Ip() method in the Fiber driver does not work properly](#fix-the-problem-that-the-ctx-request-ip-method-in-the-fiber-driver-does-not-work-properly) +- [The WhereBetween method in Orm does not support strings](#the-wherebetween-method-in-orm-does-not-support-strings) + +## v1.15.9 + +- [Fix the problem that the Cursor method in Orm leaks memory in some cases](#fix-the-problem-that-the-cursor-method-in-orm-leaks-memory-in-some-cases) +- [Fix the problem that OnOneServer fails to work when using second-level tasks in Schedule](#fix-the-problem-that-ononeserver-fails-to-work-when-using-second-level-tasks-in-schedule) +- [Make the default Timestamps in the generated migration file change to TimestampsTz](#make-the-default-timestamps-in-the-generated-migration-file-change-to-timestampstz) + +## v1.15.10 + +- [Fix the problem that the Where condition may be mixed when Orm Query is reused](#fix-the-problem-that-the-where-condition-may-be-mixed-when-orm-query-is-reused) + +## v1.15.11 + +- [Fix bcc and cc cannot be set expectly when sending mail](#fix-bcc-and-cc-cannot-be-set-expectly-when-sending-mail) +- [Fix sending mail via queue returns incorrect error](#fix-sending-mail-via-queue-returns-incorrect-error) +- [Fix the orm create events can be triggered when creating multiple records](#fix-the-orm-create-events-can-be-triggered-when-creating-multiple-records) + +## v1.15.12 + +- [Fix Transaction does not rollback when panic in closure](#fix-transaction-does-not-rollback-when-panic-in-closure) + +## Upgrade Guide + +**Estimated Upgrade Time: 10 Minutes** + +As [Golang v1.21 is no longer maintained](https://endoflife.date/go), the Golang version of Goravel supports has been upgraded from 1.21 to 1.22. Please update the version in the go.mod file. + +### 1. Updating Dependencies + +``` +go get github.com/goravel/framework@v1.15.9 + +// If using gin +go get github.com/goravel/gin@v1.3.3 + +// If using fiber +go get github.com/goravel/fiber@v1.3.6 + +// If using redis +go get github.com/goravel/redis@v1.3.1 + +// If using S3 +go get github.com/goravel/s3@v1.3.2 + +// If using Oss +go get github.com/goravel/oss@v1.3.2 + +// If using Cos +go get github.com/goravel/cos@v1.3.2 + +// If using Minio +go get github.com/goravel/minio@v1.3.2 + +// If using Cloudinary +go get github.com/goravel/cloudinary@v1.3.1 +``` + +``` +go mod tidy +``` + +### 2. If you are using the Postgresql driver + +Need to modify accordingly: [The name of Postgresql driver changes to Postgres](#the-name-of-postgresql-driver-changes-to-postgres) + +### 3. If you are using the Orm.Transaction method + +Need to modify accordingly: [Modify the Orm.Transaction method callback parameter type](#modify-the-ormtransaction-method-callback-parameter-type) + +### 4. If you are using the Delete or ForceDelete method of Orm + +Need to modify accordingly: [Optimize the Delete and ForceDelete methods of Orm](#optimize-the-delete-and-forcedelete-methods-of-orm) + +### 5. If you are using the Decrement and Increment methods of Cache + +Need to modify accordingly: [Optimize the Decrement and Increment methods of Cache](#optimize-the-decrement-and-increment-methods-of-cache) + +### 6. If you are using the Worker method of the Queue module + +Need to modify accordingly: [Optimize the Worker method of the Queue module](#optimize-the-worker-method-of-the-queue-module) + +### 7. If you are using the Call method of Artisan + +Need to modify accordingly: [Optimize the Call method of Artisan](#optimize-the-call-method-of-artisan) + +### 8. If you are using the Clear method of Testing.Database + +Need to modify accordingly: [Rename the Clear method of Testing.Database to Shutdown](#rename-the-clear-method-of-testing-database-to-shutdown) + +### 9. If you are using the Build method of Testing.Database + +Need to modify accordingly: [Optimize the Build method of Testing.Database](#optimize-the-build-method-of-testing-database) + +### 10. If you are using the Migration module + +Modify the configuration in `config/database.go`: + +```go +-- "migrations": "migrations", +++ "migrations": map[string]any{ +++ "driver": "sql", +++ "table": "migrations", +++ }, +``` + +### 11. If you are using the Request.Input\* method + +Need to modify accordingly: [Optimize the Request.Input\* method](#optimize-the-request-input-method) + +### 12. If you are using the validation.PrepareForValidation method + +Need to modify accordingly: [Optimize the validation.PrepareForValidation method](#optimize-the-validation-prepareforvalidation-method) + +### 13. If you are using the Mail module + +Modify the way `Subject` is set: + +```go +-- import "github.com/goravel/framework/contracts/mail" +++ import "github.com/goravel/framework/mail" + +-- Content(mail.Content{Subject: "Subject", Html: "

Hello Goravel

"}) +++ Content(mail.Html("

Hello Goravel

")).Subject("Subject") +``` + +If you are using the `From` method: + +```go +-- import "github.com/goravel/framework/contracts/mail" +++ import "github.com/goravel/framework/mail" + +-- From(mail.From{Address: testFromAddress, Name: testFromName} +++ From(mail.Address(testFromAddress, testFromName) +``` + +If you are using the `Queue` method: + +```go +-- import "github.com/goravel/framework/contracts/mail" +++ import "github.com/goravel/framework/mail" + +-- Queue(mail.Queue{Connection: "high", Queue: "mail"}) +++ Queue(mail.Queue().Connection("high").Queue("mail")) +``` + +### 14. If you are using the validation.PrepareForValidation method + +Need to modify accordingly: [Optimize the validation.PrepareForValidation method](#optimize-the-validation-prepareforvalidation-method) + +## Feature Introduction + +### Migration supports using Go language migration + +Previously, the framework only supported SQL migrations. When you wanted to switch databases, the differences in SQL syntax between different databases made the migration process extremely difficult. In addition, code could not be executed in migration files, making it impossible to perform logical judgments when repairing data. + +Now, the framework supports generating migration files directly using Go language, making it easy for developers to write complex migration logic. However, in the current version, the modification of table fields has not been implemented, only supporting operations such as creating tables, deleting tables, and creating indexes. If you want to make modifications, you need to use the `Sql` method to execute SQL statements directly. The ability to modify table fields will be supported in future versions. + +In version v1.15, the framework supports both Go language migration (default) and SQL migration, but SQL migration will be removed in version v1.16. + +#### Switching from SQL migration to Go language migration + +If you are using SQL migration, you can switch to Go language migration by following these steps: + +1. Modify the configuration in `config/database.go`; + +```go +-- "migrations": "migrations", +++ "migrations": map[string]any{ +++ "driver": "default", +++ "table": "migrations", +++ }, +``` + +2. Use the `go run . artisan make:migration {NAME}` command to create a migration file; + +Execute the migration and rollback statements in the original SQL migration file in the `Up` and `Down` methods of the generated file, and use the `facades.Schema().HasTable` method to check if the table exists: + +```go +func (r *M20241207095921CreateUsersTable) Up() error { + if !facades.Schema().HasTable("users") { + return facades.Schema().Sql({SQL}) + } + + return nil +} +``` + +3. Register the migration file in the `database/kernel.go` file; + +Create a new `database/kernel.go` file and register migration files and Seeders: + +```go +package database + +import ( + "github.com/goravel/framework/contracts/database/schema" + "github.com/goravel/framework/contracts/database/seeder" + + "goravel/database/migrations" + "goravel/database/seeders" +) + +type Kernel struct { +} + +func (kernel Kernel) Migrations() []schema.Migration { + return []schema.Migration{ + &migrations.M20241207095921CreateUsersTable{}, + } +} + +func (kernel Kernel) Seeders() []seeder.Seeder { + return []seeder.Seeder{ + &seeders.DatabaseSeeder{}, + } +} +``` + +4. Modify the `app/providers/database_service_provider.go` file to complete the registration, and move the `Seeder` originally registered here to `database/kernel.go::Seeders`; + +```go +-- func (receiver *DatabaseServiceProvider) Boot(app foundation.Application) { +-- facades.Seeder().Register([]seeder.Seeder{ +-- &seeders.DatabaseSeeder{}, +-- }) +-- } +++ func (receiver *DatabaseServiceProvider) Boot(app foundation.Application) { +++ kernel := database.Kernel{} +++ facades.Schema().Register(kernel.Migrations()) +++ facades.Seeder().Register(kernel.Seeders()) +++ } +``` + +5. Backup the existing `migrations` table data, then delete the `migrations` table; + +6. Execute the `go run . artisan migrate` command to perform the migration, after the migration is complete, a new `migrations` table will be generated. + +[View Documentation](../database/migrations.md) + +### Testing supports HTTP testing + +goravel/framework: v1.15.0 + +The framework has added the `Testing.Http` module, which supports testing HTTP requests, allowing you to simulate requests, get responses, and assert responses. + +[View Documentation](../testing/http-tests.md) + +### HTTP supports return Stream + +goravel/framework: v1.15.0 + +[View Documentation](../the-basics/response.md#return-stream) + +### HTTP supports setting timeout + +goravel/framework: v1.15.0 + +You can set the timeout time by configuring `http.request_timeout` in the `config/http.go` file, which defaults to 3 seconds. + +### HTTP supports setting custom recovery method + +goravel/framework: v1.15.0 + +[View Documentation](../the-basics/request.md#custom-recovery) + +### Request supports configure Filter + +goravel/framework: v1.15.0 + +[View Documentation](../the-basics/validation.md#filter-input-data) + +### Request adds the BindQuery method + +goravel/framework: v1.15.0 + +Support using `ctx.Request().BindQuery()` to bind parameters directly from the link. + +[View Documentation](../the-basics/request.md#bind-query) + +### Validation supports Regex rules + +goravel/framework: v1.15.0 + +```go +validator, err := ctx.Request().Validate(map[string]string{ + "code": `required|regex:^\d{4,6}$`, +}) +``` + +### Schedule supports control log output + +goravel/framework: v1.15.0 + +When `app.debug` is `false`, only `error` level logs will be output. + +### Schedule adds the Shutdown method + +goravel/framework: v1.15.0 + +The `Shutdown` method can be used to gracefully stop the Schedule. + +[View Documentation](../digging-deeper/task-scheduling.md#stopping-the-scheduler) + +### Mail supports Mailable template + +goravel/framework: v1.15.0 + +[View Documentation](../digging-deeper/mail.md#using-mailable) + +### The trace in error log output supports jumping + +goravel/framework: v1.15.0 + +In the error log output, clicking on the trace will jump to the line of code where the error occurred. + +### Log supports printing key-value pairs in Context + +goravel/framework: v1.15.0 + +```go +ctx.WithValue("a", "b") +facades.Log().WithContext(ctx).Info("Hello Goravel") + +// Output: +[2024-12-15 16:36:58] local.info: Hello Goravel +Context: map[a:b] +``` + +### Support directly setting DSN to connect to the database + +goravel/framework: v1.15.0 + +[View Documentation](../orm/getting-started.md#dsn) + +### The Create method of Orm supports using map to create + +goravel/framework: v1.15.0 + +[View Documentation](../orm/getting-started.md#create) + +### Orm adds configuration items + +goravel/framework: v1.15.0 + +The configurations are for specific situations and are not required for normal use, not add them to the configuration file by default. + +```go +// config/database.go +"{driver_name}": map[string]any{ + "driver": "{driver_name}", + "host": config.Env("DB_HOST", "127.0.0.1"), + ... +++ "schema": "goravel",// Set the default schema for the connection, only for Postgres and Sqlserver +++ "no_lower_case": false,// Set whether to convert the table name to lowercase +++ "name_replacer": strings.NewReplacer("id", "ID"),// Set the columns name replacement +}, +``` + +### Orm adds Restore method + +goravel/framework: v1.15.0 + +Add the `Restore` method to the `Orm` module, which can be used to restore soft deleted data, and add `Restored`, `Restoring` events. + +[View Documentation](../orm/getting-started.md#restore) + +### Orm's Log integrated Log module + +goravel/framework: v1.15.0 + +Previously, Orm's log output was directly output to the console, now Orm's log output will be integrated into the Log module, and can be printed to the console and log file at the same time. + +### Postgres and Sqlserver drivers support Schema + +goravel/framework: v1.15.0 + +[View Documentation](../orm/getting-started.md#schema) + +### Add about command + +goravel/framework: v1.15.0 + +Add the `about` command, which can be used to view the framework version, configuration, etc. + +```bash +go run . artisan about +``` + +### Add db:show command + +goravel/framework: v1.15.0 + +Add the `db:show` command, which can be used to view the database connection information. + +```bash +go run . artisan db:show +``` + +### Add db:table command + +goravel/framework: v1.15.0 + +Add the `db:table` command, which can be used to view the table structure. + +```bash +go run . artisan db:table +go run . artisan db:table users +``` + +### Optimize Artisan output style + +goravel/framework: v1.15.0 + +Optimize Artisan output style, add color, making the output more beautiful. + +### Auth adds the Id method + +goravel/framework: v1.15.0 + +```go +id, err := facades.Auth(ctx).ID() +``` + +### Multiple Auth.Guard can set their own TTL + +goravel/framework: v1.15.0 + +Previously, multiple Guards shared the `jwt.ttl` configuration. Now you can set the TTL for each Guard separately by setting it in the `config/auth.go` file. If not set, the `jwt.ttl` configuration will be used by default. + +```go +// config/auth.go +"guards": map[string]any{ + "user": map[string]any{ + "driver": "jwt", +++ "ttl": 60, + }, +}, +``` + +### The name of Postgresql driver changes to Postgres + +goravel/framework: v1.15.0 + +The name of the Postgresql driver has been changed to `postgres`. If you are using the Postgresql driver, you need to modify the configration file: + +```go +// config/database.go +"postgres": map[string]any{ + -- "driver": "postgresql", + ++ "driver": "postgres", + "host": config.Env("DB_HOST", "127.0.0.1"), +} +``` + +### Modify the Orm.Transaction method callback parameter type + +goravel/framework: v1.15.0 + +The `facades.Orm().Transaction()` method callback parameter type has been changed from `func(tx orm.Transaction) error` to `func(tx orm.Query) error`, if you are using this method, please modify accordingly. + +```go +-- facades.Orm().Transaction(func(tx orm.Transaction) error { +++ facades.Orm().Transaction(func(tx orm.Query) error { + var user models.User + + return tx.Find(&user, user.ID) +}) +``` + +### Optimize the Delete and ForceDelete methods of Orm + +goravel/framework: v1.15.0 + +If you are passing an ID to the `Delete` or `ForceDelete` method to delete data, use the `Where` method instead: + +```go +-- facades.Orm().Query().Delete(&models.User{}, 10) +++ facades.Orm().Query().Where("id", 10).Delete(&models.User{}) + +-- facades.Orm().Query().Delete(&models.User{}, []uint{1, 2, 3}) +++ facades.Orm().Query().WhereIn("id", []uint{1, 2, 3}).Delete(&models.User{}) + +-- facades.Orm().Query().ForceDelete(&models.User{}, 10) +++ facades.Orm().Query().ForceDelete("id", 10).Delete(&models.User{}) +``` + +`Delete` and `ForceDelete` methods support deleting data without passing parameters: + +```go +res, err := facades.Orm().Query().Model(&models.User{}).Where("id", 1).Delete() +res, err := facades.Orm().Query().Table("users").Where("id", 1).Delete() +``` + +### Optimize the Decrement and Increment methods of Cache + +goravel/framework: v1.15.0 + +The input and output types of the `Decrement` and `Increment` methods have been changed from `int` to `int64`: + +```go +-- Decrement(key string, value ...int) (int, error) +++ Decrement(key string, value ...int64) (int64, error) + +-- Increment(key string, value ...int) (int, error) +++ Increment(key string, value ...int64) (int64, error) +``` + +### Optimize the Call method of Artisan + +goravel/framework: v1.15.0 + +The `facades.Artisan().Call()` method will panic if an error is encountered during execution. It now returns an error, so handle the error if you are using this method. + +```go +err := facades.Artisan().Call("command:name") +``` + +### Rename the Clear method of Testing.Database to Shutdown + +goravel/framework: v1.15.0 + +In order to keep the method name consistent with other modules, we renamed the `Clear` method to `Shutdown`. + +```go +database, err := facades.Testing().Docker().Database() +-- err := database.Clear() +++ err := database.Shutdown() +``` + +### Optimize the Build method of Testing.Database + +goravel/framework: v1.15.0 + +Previously, when calling the `Build` method, the database migration would be performed automatically. After the upgrade, you need to manually call the `Migrate` method to perform the migration, making database control more flexible. + +```go +database, err := facades.Testing().Docker().Database() +err := database.Build() +++ err := database.Migrate() +``` + +### Optimize the Request.Input\* method + +goravel/framework: v1.15.0 + +goravel/gin: v1.3.0 + +goravel/fiber: v1.3.0 + +Previously, the `Request.Input*` method could only get data from the `Body`, now it will look for data in the `Body`, `Query`, and `Param` in order. Previously, when passing a second parameter (default value) to the `Request.Input*` method, if the `key` existed but was empty, the default value would be returned. Now, an empty string will be returned, as an empty string is also a valid value, only when the `key` does not exist, the default value will be returned. + +You need to check all the places where the `Request.Input*` method is used to ensure that the parameters passed are correct and the return values are as expected. + +### Optimize the validation.PrepareForValidation method + +goravel/framework: v1.15.0 + +Modify the input parameter type and add the `http.Context` parameter: + +```go +import github.com/goravel/framework/validation + +-- validator, err := facades.Validation().Make(input, rules, validation.PrepareForValidation(func(data validationcontract.Data) error { +++ validator, err := facades.Validation().Make(input, rules, validation.PrepareForValidation(func(ctx http.Context, data validationcontract.Data) error { + if name, exist := data.Get("name"); exist { + return data.Set("name", name) + } + + return nil +})) +``` + +### Optimize the Worker method of the Queue module + +goravel/framework: v1.15.0 + +When the `Worker` method does not need to set parameters, it can be kept empty: + +```go +-- facades.Queue().Worker(nil).Run() +++ facades.Queue().Worker().Run() +``` + +When you need to set parameters, the parameters are changed from pointers to instances: + +```go +-- facades.Queue().Worker(&queue.Args{Connection: "redis").Run() +++ facades.Queue().Worker(queue.Args{Connection: "redis").Run() +``` + +### Go Migration supports Boolean field + +goravel/framework: v1.15.3 + +```go +table.Boolean("is_admin") +``` + +### Go Migration supports custom field + +goravel/framework: v1.15.3 + +If you are using column types that framework does not support yet, you can use the `Column` method to customize the field type: + +```go +table.Column("geometry", "geometry") +``` + +### Optimize Artisan log output rules + +goravel/framework: v1.15.3 + +Previously, Artisan log only output error level logs, now all levels of logs will be output. If you want to disable console printing logs and are using the `single` or `daily` log driver, please set the `logging.channels.single.print` or `logging.channels.daily.print` configuration to `false`. + +### Fix the problem that ctx is nil in PrepareForValidation + +goravel/framework: v1.15.4 + +goravel/gin: v1.3.3 + +goravel/fiber: v1.3.3 + +Before the fix, `ctx` was always `nil` in the `PrepareForValidation` method, now it will be correctly passed as a parameter. If you are using the `validation.PrepareForValidation` method, please modify accordingly. + +```go +import ( + github.com/goravel/framework/validation + contarctsvalidate "github.com/goravel/framework/contracts/validation" +) + +-- validation.PrepareForValidation(func(ctx http.Context, data contarctsvalidate.Data) error { +++ validation.PrepareForValidation(ctx, func(ctx http.Context, data contarctsvalidate.Data) error { +``` + +### Fix the problem that the Orm WithContext method reports an error in Fiber driver under high concurrency + +goravel/framework: v1.15.4 + +goravel/fiber: v1.3.3 + +For details: [#866](https://github.com/goravel/framework/pull/866) + +### Optimize the packaging volume + +goravel/framework: v1.15.4 + +For details: [#865](https://github.com/goravel/framework/pull/865) + +### Optimize the problem that the model ID is nested multiple times + +goravel/framework: v1.15.4 + +For details: [#898](https://github.com/goravel/framework/pull/898) + +### Add artisan command alias + +goravel/framework: v1.15.4 + +``` +// Before +go run . artisan key:generate + +// After +./artisan key:generate +``` + +### Fix the problem that Throttle fails to store in Redis driver + +goravel/framework: v1.15.5 + +goravel/redis: v1.3.1 + +When using the Redis driver, `Throttle` fails to store normally, causing the limit to fail. + +Issue: [#625](https://github.com/goravel/goravel/issues/625) + +### Fix the problem that Fallback fails to work in Fiber driver + +goravel/framework: v1.15.5 + +goravel/fiber: v1.3.4 + +When using the Fiber driver, if `Fallback` is set, other routes will fail to work. + +Issue: [#624](https://github.com/goravel/goravel/issues/624) + +### Fix the problem that the Orm WithContext method reports an error in concurrent execution + +goravel/framework: v1.15.6 + +When using the `WithContext` method to set `Context`, it was reported an error in concurrent execution. + +### Upgrade Carbon + +goravel/framework: v1.15.7 + +[dromara/carbon](https://github.com/dromara/carbon) v2.5.5 or later versions have introduced new features, causing some framework functions to behave abnormally. Notice: dromara/carbon v2.6 or later versions are not supported yet, will be supported in Goravel v1.16. + +### Fix the problem that facades.Testing().Docker().Database() reports an error + +goravel/framework: v1.15.8 + +Issue: [#672](https://github.com/goravel/goravel/issues/672) + +### Fix the problem that the ctx.Request().Ip() method in the Fiber driver does not work properly + +goravel/fiber: v1.3.6 + +Previously, the `ctx.Request().Ip()` method always returned `127.0.0.1`. After the fix, new configuration items `http.drivers.fiber.proxy_header`, `http.drivers.fiber.enable_trusted_proxy_check` and `http.drivers.fiber.trusted_proxies` have been added to set the proxy header and trusted proxy IP addresses. + +Issue: [#678](https://github.com/goravel/goravel/issues/678) + +### The WhereBetween method in Orm does not support strings + +goravel/framework: v1.15.8 + +Issue: [#1036](https://github.com/goravel/goravel/issues/1036) + +### Fix the problem that the Cursor method in Orm leaks memory in some cases + +goravel/framework: v1.15.9 + +When getting `rows`, the `chan` is not closed correctly, causing memory leaks. + +### Fix the problem that OnOneServer fails to work when using second-level tasks in Schedule + +goravel/framework: v1.15.9 + +Issue: [#690](https://github.com/goravel/goravel/issues/690) + +### Make the default Timestamps in the generated migration file change to TimestampsTz + +goravel/framework: v1.15.9 + +Issue: [#699](https://github.com/goravel/goravel/issues/699) + +### Fix the problem that the Where condition may be mixed when Orm Query is reused + +goravel/framework: v1.15.10 + +Issue: [#732](https://github.com/goravel/goravel/issues/732) + +### Fix bcc and cc cannot be set expectly when sending mail + +goravel/framework: v1.15.11 + +Issue: [#737](https://github.com/goravel/goravel/issues/737) + +### Fix sending mail via queue returns incorrect error + +goravel/framework: v1.15.11 + +PR: [#1148](https://github.com/goravel/framework/pull/1148) + +### Fix the orm create events can be triggered when creating multiple records + +goravel/framework: v1.15.11 + +Issue: [#738](https://github.com/goravel/goravel/issues/738) + +### Fix Transaction does not rollback when panic in closure + +goravel/framework: v1.15.12 + +Issue: [#762](https://github.com/goravel/goravel/issues/762) From aa25869be9074fe576cd134147d44ccc2b4bf98d Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:03 +0800 Subject: [PATCH 059/163] New translations v1.16.md (Uzbek) [skip ci] Update translations (Uzbek) v1.16.md --- uz_UZ/upgrade/v1.16.md | 985 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 985 insertions(+) create mode 100644 uz_UZ/upgrade/v1.16.md diff --git a/uz_UZ/upgrade/v1.16.md b/uz_UZ/upgrade/v1.16.md new file mode 100644 index 000000000..995f6dd2d --- /dev/null +++ b/uz_UZ/upgrade/v1.16.md @@ -0,0 +1,985 @@ +# Upgrading To v1.16 From v1.15 + +## Exciting New Features 🎉 + +- [Add facades.DB()](#add-facades-db) +- [Add facades.Http()](#add-facades-http) +- [Reconstruct facades.Queue()](#reconstruct-facades-queue) +- [facades.Auth() supports custom driver](#facades-auth-supports-custom-driver) +- [make:\* commands support automatic registration](#make-commands-support-automatic-registration) +- [Goravel Installer supports selecting driver](#goravel-installer-supports-selecting-driver) + +## Enhancements 🚀 + +- [Split Database Driver](#split-database-driver) +- [Orm adds features](#orm-adds-features) +- [Support creating Model based on data table](#support-creating-model-based-on-data-table) +- [Support runtime dynamic SQL statement](#support-runtime-dynamic-sql-statement) +- [Migration adds features](#migration-adds-features) +- [Grpc adds Shutdown method](#grpc-adds-shutdown-method) +- [Artisan adds disable print colors option](#artisan-adds-disable-print-colors-option) +- [Encrypt and decrypt env file](#encrypt-and-decrypt-env-file) +- [Send email supports setting Header](#send-email-supports-setting-header) +- [Installer supports self upgrade](#installer-supports-self-upgrade) +- [Localization supports embed loading](#localization-supports-embed-loading) +- [Schedule adds features](#schedule-adds-features) +- [Request adds features](#request-adds-features) +- [Route adds features](#route-adds-features) +- [Testing supports creating Cache image](#testing-supports-creating-cache-image) +- [Different JWT Guard supports different configurations](#different-jwt-guard-supports-different-configurations) +- [ServiceProvider no longer depends on order](#serviceprovider-no-longer-depends-on-order) + +## Breaking Changes 🛠 + +- [Remove SQL Migration](#remove-sql-migration) +- [Optimize Config module methods default value type](#optimize-config-module-methods-default-value-type) +- [Optimize Orm methods](#optimize-orm-methods) +- [Optimize Path methods](#optimize-path-methods) +- [Optimize Request methods](#optimize-request-methods) +- [Optimize console Confirm methods](#optimize-console-confirm-methods) +- [Optimize Session custom driver](#optimize-session-custom-driver) +- [Optimize Testing.Request methods](#optimize-testing-request-methods) +- [Optimize Carbon methods](#optimize-carbon-methods) +- [Optimize str.Snake methods](#optimize-str-snake-methods) +- [goravel/cloudinary is no longer maintained](#goravelcloudinary-is-no-longer-maintained) + +## v1.16.1 + +- [Fix bcc and cc cannot be set expectly when sending mail](#fix-bcc-and-cc-cannot-be-set-expectly-when-sending-mail) +- [Fix sending mail via queue returns incorrect error](#fix-sending-mail-via-queue-returns-incorrect-error) +- [Fix the orm create events can be triggered when creating multiple records](#fix-the-orm-create-events-can-be-triggered-when-creating-multiple-records) +- [Fix the make:package command generates incorrect code](#fix-the-make-package-command-generates-incorrect-code) +- [Fix the path is incorrect when publishing package files](#fix-the-path-is-incorrect-when-publishing-package-files) + +## v1.16.3 + +- [Fix Transaction does not rollback when panic in closure](#fix-transaction-does-not-rollback-when-panic-in-closure) +- [Fix errors if adding or removing a column with a separate migration script](#fix-errors-if-adding-or-removing-a-column-with-a-separate-migration-script) +- [Fix the breaking change of Orm Select method](#fix-the-breaking-change-of-orm-select-method) + +## v1.16.4 + +- [Fix commands cannot be run concurrently](#fix-commands-cannot-be-run-concurrently) + +## v1.16.5 + +- [Fix Queue cannot be shut down as expected](#fix-queue-cannot-be-shut-down-as-expected) + +## v1.16.6 + +- [Fix DB cache is not reset when fresh orm](#fix-db-cache-is-not-reset-when-fresh-orm) +- [Fix log file rotation issue in daily logger](#fix-log-file-rotation-issue-in-daily-logger) +- [Fix the paginate method will report an error when selecting and renaming only one column](#fix-the-paginate-method-will-report-an-error-when-selecting-and-renaming-only-one-column) +- [Fix Cursor cannot scan json column](#fix-cursor-cannot-scan-json-column) + +## v1.16.7 + +- [Fix Distinct has no effect when using with Count](#fix-distinct-has-no-effect-when-using-with-count) +- [DB.Insert can not operate nil columns as expected](#db-insert-can-not-operate-nil-columns-as-expected) +- [Fix incorrect orm nested relationships load](#fix-incorrect-orm-nested-relationships-load) + +## v1.16.8 + +- [Fix delay task issue when queue concurrency is greater than 1](#fix-delay-task-issue-when-queue-concurrency-is-greater-than-1) + +## Upgrade Guide + +As [Golang v1.22 is no longer maintained](https://endoflife.date/go), the Golang version of Goravel supports has been upgraded from 1.22 to 1.23. + +goravel/example project from v1.15 to v1.16 PR can be used as an upgrade reference: [goravel/example#68](https://github.com/goravel/example/pull/68). + +### 1. Update Dependencies + +```shell +go get github.com/goravel/framework@latest + +// If using gin +go get github.com/goravel/gin@latest + +// If using fiber +go get github.com/goravel/fiber@latest + +// If using redis +go get github.com/goravel/redis@latest + +// If using S3 +go get github.com/goravel/s3@latest + +// If using Oss +go get github.com/goravel/oss@latest + +// If using Cos +go get github.com/goravel/cos@latest + +// If using Minio +go get github.com/goravel/minio@latest + +go mod tidy +``` + +### 2. Modify Database Configuration + +Delete the `connections` in the database configuration file `config/database.go` that you don't need, and install the database driver you need. + +For example, Postgres: + +1. Install the driver package + +```shell +go get github.com/goravel/postgres +``` + +2. Add `postgres.ServiceProvider` to the `config/app.go` file + +```go +// config/app.go +import "github.com/goravel/postgres" + +"providers": []foundation.ServiceProvider{ + ... + &postgres.ServiceProvider{}, +}, +``` + +3. Modify the configuration in the `config/database.go` file + +```diff +// config/database.go +import ( + "github.com/goravel/framework/contracts/database/driver" + postgresfacades "github.com/goravel/postgres/facades" +) + +"connections": map[string]any{ + "postgres": map[string]any{ + ... +++ "via": func() (driver.Driver, error) { +++ return postgresfacades.Postgres("postgres") +++ }, + }, +}, +``` + +### 3. Modify auth.go configuration file + +```diff +// config/auth.go + +// Supported: "jwt" +"guards": map[string]any{ + "user": map[string]any{ + "driver": "jwt", +++ "provider": "user", + }, +}, + +++ // Supported: "orm" +++ "providers": map[string]any{ +++ "user": map[string]any{ +++ "driver": "orm", +++ }, +++ }, +``` + +### 4. Modify session.go configuration file + +```diff +// config/session.go + +-- "driver": config.Env("SESSION_DRIVER", "file"), +++ "default": config.Env("SESSION_DRIVER", "file"), +++ "drivers": map[string]any{ +++ "file": map[string]any{ +++ "driver": "file", +++ }, +++ }, +``` + +### 5. Modify queue.go configuration file + +- If you are using the Redis driver of the Queue module, you need to modify accordingly: [Optimize Queue module configuration](#optimize-queue-module-configuration). + +- If you are not using it or want to use the database driver in the future, you need to modify the configuration in the `config/queue.go` file: + +```diff +// config/queue.go + +-- // Drivers: "sync", "redis" +++ // Drivers: "sync", "database", "custom" +"connections": map[string]any{ + "sync": map[string]any{ + "driver": "sync", + }, +-- "redis": map[string]any{ +-- "driver": "redis", +-- "connection": "default", +-- "queue": config.Env("REDIS_QUEUE", "default"), +-- }, +++ "database": map[string]any{ +++ "driver": "database", +++ "connection": "postgres", +++ "queue": "default", +++ "concurrent": 1, +++ }, +}, + +++ "failed": map[string]any{ +++ "database": config.Env("DB_CONNECTION", "postgres"), +++ "table": "failed_jobs", +++ }, +``` + +Add the migration file required for the database driver: [database/migrations/20210101000002_create_jobs_table.go](https://github.com/goravel/goravel/blob/master/database/migrations/20210101000002_create_jobs_table.go), and register the migration file in the `database/kernel.go` file. + +### 6. If you need to use HTTP Client + +Add the HTTP Client configuration item in the `config/http.go` file: + +```diff +// config/http.go +++ "client": map[string]any{ +++ "base_url": config.GetString("HTTP_CLIENT_BASE_URL"), +++ "timeout": config.GetDuration("HTTP_CLIENT_TIMEOUT"), +++ "max_idle_conns": config.GetInt("HTTP_CLIENT_MAX_IDLE_CONNS"), +++ "max_idle_conns_per_host": config.GetInt("HTTP_CLIENT_MAX_IDLE_CONNS_PER_HOST"), +++ "max_conns_per_host": config.GetInt("HTTP_CLIENT_MAX_CONN_PER_HOST"), +++ "idle_conn_timeout": config.GetDuration("HTTP_CLIENT_IDLE_CONN_TIMEOUT"), +++ }, +``` + +### 7. If using goravel/redis driver + +Need to modify the configuration in the `config/cache.go` file: + +```diff +// config/cache.go +"redis": map[string]any{ + "driver": "custom", + "connection": "default", + "via": func() (cache.Driver, error) { +-- return redisfacades.Redis("redis"), nil +++ return redisfacades.Cache("redis") + }, +}, +``` + +### 8. If using carbon.DateTime etc. methods + +Need to modify accordingly: [Optimize Carbon methods](#optimize-carbon-methods) + +### 9. If using session custom driver + +Need to modify accordingly: [Optimize Session custom driver](#optimize-session-custom-driver) + +### 10. If using methods of facades.Config() + +Need to modify accordingly: [Modify Config module methods default value type](#modify-config-module-methods-default-value-type) + +### 11. If Using SQL Migrations + +Need to modify accordingly: [Remove SQL Migration](#remove-sql-migration) + +### 12. If Using Orm + +Need to modify accordingly: [Optimize Orm methods](#optimize-orm-methods) + +### 13. If Using Path Method + +The `path` method returns the absolute path, if you are using it, you need to check if you need to modify: [Optimize Path method](#optimize-path-method) + +### 14. If Using `ctx.Request().InputMap` Method + +Need to modify accordingly: [Optimize Request method](#optimize-request-method) + +### 15. If Using `console.Confirm` Method + +Need to modify accordingly: [Optimize console Confirm method](#optimize-console-confirm-method) + +### 16. If Using Testing.Request method + +Need to modify accordingly: [Optimize Testing.Request method](#optimize-testing-request-method) + +## Feature Introduction + +### Add facades.DB() + +Add the `facades.DB()` module, which is convenient for performing native database operations, faster than ORM. + +[View Document](../database/getting-started.md) + +### Add facades.Http() + +Add the `facades.Http()` module, which is convenient for performing HTTP operations. + +[View Document](../digging-deeper/http-client.md) + +### Reconstruct facades.Queue() + +- Before v1.15, Queue only supported sync and Redis drivers, starting from v1.16, it supports database and custom driver. + +- Add `jobs` and `failed_jobs` table, used to store tasks and failed tasks. + +- Add `queue:retry` command, used to retry failed tasks. + +- Add `queue:failed` command, used to view failed tasks. + +- Support setting the number of retries when starting the queue task. + +[View Document](../digging-deeper/queues.md) + +### facades.Auth() supports custom driver + +Before v1.15, Auth only supported JWT driver, starting from v1.16, it supports Session and custom driver, please [view document](../security/authentication.md#custom-driver). + +### make:\* commands support automatic registration + +The files`make:migration` and `make:seeder`, etc. commands generated files will be automatically registered to the framework after generation, no longer need to manually register like before. + +### Goravel Installer supports selecting driver + +When installing a new project using Goravel Installer, you can select different drivers, such as: you can choose to install goravel/gin or goravel/fiber, etc. + +### Split Database Driver + +Before multiple database drivers were integrated in the framework, which increased the software package size. Starting from v1.16, the database driver will be a separate package, so you only need to install the database driver you need. + +| Database Type | Driver Package | +| ------------- | ------------------------------------------------------------------------------------ | +| Postgres | [github.com/goravel/postgres](https://github.com/goravel/postgres) | +| MySQL | [github.com/goravel/mysql](https://github.com/goravel/mysql) | +| Sqlserver | [github.com/goravel/sqlserver](https://github.com/goravel/sqlserver) | +| SQLite | [github.com/goravel/sqlite](https://github.com/goravel/sqlite) | + +### Orm adds features + +- Support querying JSON fields, [view document](../orm/getting-started.md#where). + +- Support updating JSON fields, [view document](../orm/getting-started.md#update-json-fields). + +- Model supports setting the `GlobalScope` method, which restricts the scope of the query, update, and delete operations: + +```go +import "github.com/goravel/framework/contracts/orm" + +type User struct { + orm.Model + Name string +} + +func (r *User) GlobalScopes() []func(orm.Query) orm.Query { + return []func(orm.Query) orm.Query{ + func(query orm.Query) orm.Query { + return query.Where("name", "goravel") + }, + } +} +``` + +### Support creating Model based on data table + +`make:model` command adds `--table` option, used to create Model based on data table: + +```shell +./artisan make:model --table=users User + +// If the Model already exists, you can use the -f option to force overwrite +./artisan make:model --table=users -f User +``` + +### Support runtime dynamic SQL statement + +Add the `EnableQueryLog` method, which is used to enable query log: + +```go +ctx := db.EnableQueryLog(ctx) + +facades.Orm().WithContext(ctx).Query() +facades.DB().WithContext(ctx).Table() + +queryLogs := db.GetQueryLog(ctx) +ctx := db.DisableQueryLog(ctx) +``` + +### Migration adds features + +- Add the `Change` method to modify the table structure(Apply to Postgres, MySQL, Sqlserver): + +```go +table.String("name").Change() +``` + +- Add the `RenameColumn` method, for renaming the table column: + +```go +table.RenameColumn("old_name", "new_name") +``` + +- Add the `Comment` method, for adding a comment to the table (Apply to Postgres, MySQL): + +```go +table.Comment("user table") +``` + +- Add the `First` method, for setting the field as the first field of the table (Apply to MySQL): + +```go +table.String("name").First() +``` + +- Add the `After` method, for setting the field as the last field of the table (Apply to MySQL): + +```go +table.String("name").After("id") +``` + +- Add the `Morphs`, `NullableMorphs`, `NumericMorphs`, `UuidMorphs`, `UlidMorphs` methods, used to create polymorphic association fields: + +```go +table.Morphs("morphable") +// morphable_type, morphable_id +``` + +- Add the `Uuid`, `Ulid` methods, used to create UUID and ULID fields: + +```go +table.Uuid("uuid") +table.Ulid("ulid") +``` + +- Add the `GeneratedAs` and `Always` methods, used to create generated columns (only PostgreSQL): + +```go +table.String("name").GeneratedAs().Always() +``` + +### Grpc adds Shutdown method + +Add the `Shutdown` method to gracefully shut down Grpc, [View Document](../the-basics/grpc.md#shutdown-grpc). + +### Artisan adds disable print colors option + +Some commands print colors by default, such as the `list` command. However, in some terminals or logs, the color values may be garbled. You can use the `--no-ansi` option to disable the print colors: + +```shell +go run . artisan list --no-ansi +``` + +### Encrypt and decrypt env file + +You may want to add the production environment env file to version control, but you don't want to expose sensitive information, you can encrypt and decrypt the env file: + +[View Document](../getting-started/installation.md#encrypt-and-decrypt-env-file) + +### Send email supports setting Header + +Add the `Headers` method, which is used to set the Header of the email. + +```go +facades.Mail().Headers(map[string]string{"X-Mailer": "Goravel"}) +``` + +### Installer supports self upgrade + +goravel/installer adds `upgrade` command, which is used to upgrade the installer itself: + +```shell +goravel upgrade +goravel upgrade v1.1.1 +``` + +### Localization supports embed loading + +When using embed loading, the language files will be compiled into the binary file and no longer need to be deployed. + +[View Document](../digging-deeper/localization.md#embed-loading) + +### Schedule adds features + +- Add the `EverySecond` method, etc., please [view document](../digging-deeper/task-scheduling.md#schedule-frequency-options). + +- Add the `schedule:run` command, which is used to manually run tasks. + +- Add the `schedule:list` method, which is used to view all tasks. + +### Request adds features + +- Before v1.15, the following `Request` binding will report an error, starting from v1.16, it supports binding multiple files: + +```go +type StoreMediaRequest struct { + Files []*multipart.FileHeader `form:"files" json:"files"` +} +``` + +- Add the `OriginPath` method, which is used to get the original route path: + +```go +ctx.Request().OriginPath() +``` + +- Add the `Info` method, which is used to get the route information: + +```go +info := ctx.Request().Info() +``` + +- Add the `Name` method, which is used to get the route name: + +```go +name := ctx.Request().Name() +``` + +- When the `http.request_timeout` configuration item is set to `0`, the request will not timeout. + +### Route adds features + +- Add the `GetRoutes` method, which is used to get all routes: + +```go +routes := facades.Route().GetRoutes() +``` + +- Add the `Name` method, which is used to set the route name: + +```go +facades.Route().Get("users", usersController.Index).Name("users.index") +``` + +Then you can use the `Info` method to get the route information: + +```go +route := facades.Route().Info("users.index") +``` + +- Add the `route:list` command, which is used to view all routes: + +```shell +./artisan route:list +``` + +### Testing supports creating Cache image + +Add the `Cache` method, which is used to create Cache image: + +```go +cache, err := facades.Testing().Docker().Cache() +``` + +### Different JWT Guard supports different configurations + +Before v1.15, the `ttl` and `secret` configuration items of the JWT Guard were global configurations, starting from v1.16, you can set different `ttl` and `secret` for different JWT Guards, [View Document](../security/authentication.md#different-jwt-guard-supports-different-configurations). + +### ServiceProvider no longer depends on order + +ServiceProvider adds an optional method `Relationship() binding.Relationship`, used to declare the dependency relationship of the current ServicerProvider, the ServiceProvider that sets this method will not depend on the registration order, and the ServiceProvider that does not set it will be registered last, for example: + +```go +type ServiceProvider struct { +} + +func (r *ServiceProvider) Relationship() binding.Relationship { + return binding.Relationship{ + Bindings: []string{ + BindingSession, + }, + Dependencies: []string{ + binding.Config, + }, + ProvideFor: []string{ + binding.Cache, + }, + } +} + +func (r *ServiceProvider) Register(app foundation.Application) {} + +func (r *ServiceProvider) Boot(app foundation.Application) {} +``` + +### Remove SQL Migration + +SQL migrations have been completely removed, please use Go language migrations. Migration steps: + +1. Remove the `migrations.driver` key in `config/database.go`; + +```go +// config/database.go +"migrations": map[string]any{ +-- "driver": "sql", + "table": "migrations", +}, +``` + +2. Convert the SQL migration files in the `database/migrations` directory to Go language migration files: + +```go +// Up Run the migrations. +func (r *M20241207095921CreateUsersTable) Up() error { + return facades.Schema().Sql({Original SQL}) +} + +// Down Reverse the migrations. +func (r *M20241207095921CreateUsersTable) Down() error { + return facades.Schema().Sql({Original SQL}) +} +``` + +3. Register the migration files in the `database/kernel.go` file; + +### Optimize Config module methods default value type + +Before the `GetString`、`GetInt`、`GetBool` method of the `Config` module had a default value type of `any`, starting from v1.16, the default value type is `string`、`int`、`bool`, to ensure type safety. + +```diff +-- GetString(path string, defaultValue ...any) string +++ GetString(path string, defaultValue ...string) string + +-- GetInt(path string, defaultValue ...any) int +++ GetInt(path string, defaultValue ...int) int + +-- GetBool(path string, defaultValue ...any) bool +++ GetBool(path string, defaultValue ...bool) bool +``` + +### Optimize Orm methods + +- Optimize the return value of the `Count`, `Exists` method: + +```diff +-- Count(count *int64) error +++ Count() (int64, error) + +-- Distinct(args ...any) Query +++ Distinct(columns ...string) Query + +-- Exists(exists *bool) error +++ Exists() (bool, error) + +-- Select(query any, args ...any) Query +++ Select(columns ...string) Query + +-- Sum(column string, dest any) error +++ Sum(column string) (int64, error) +``` + +- The `Where` method supports closures: + +```go +facades.Orm().Query().Where(func(query orm.Query) orm.Query { + return query.Where("height", 180).Where("age", 18) +}).FindOrFail(&user, 100) +// SELECT * FROM users WHERE id = 100 AND (height = 180 AND age = 18); +``` + +### Optimize Path methods + +- Add the `Resource` method + +```go +path.Resource("views/welcome.tmpl") +``` + +- The `path` method returns the absolute path + +Before the `path` method returned the relative path of the root directory, for example, `path.Config("app.go") == config/app.go`. Starting from v1.16, the `path` method returns the absolute path, for example, `path.Config("app.go") == /Users/goravel/workspace/goravel/config/app.go`. + +### Optimize Request methods + +1. Modify the default value type of the `InputMap` method: + +```diff +-- ctx.Request().InputMap(key string, defaultValue ...map[string]string) map[string]string +++ ctx.Request().InputMap(key string, defaultValue ...map[string]any) map[string]any +``` + +2. Add the `InputMapArray` method, which is used to get the array type of Map: + +```go +ctx.Request().InputMapArray(key string, defaultValue ...[]map[string]any) []map[string]any +``` + +3. Add the `Files` method, which is used to get multiple files: + +```go +ctx.Request().Files(name string) ([]filesystem.File, error) +``` + +### Optimize console Confirm methods + +Modify the return value of the `Confirm` method, simplifying the judgment logic: + +```diff +-- Confirm(question string, option ...ConfirmOption) (bool, error) +++ Confirm(question string, option ...ConfirmOption) bool +``` + +### Optimize Session custom driver + +Before, you needed to register the driver through the `facades.Session().Extend` method. Starting from v1.16, you only need to add it to the `config/session.go` configuration file: + +```diff +// app/providers/app_service_provider.go +-- facades.Session().Extend("custom", func() session.Driver { +-- return &CustomDriver{} +-- }) + +// config/session.go +"drivers": map[string]any{ + "custom": map[string]any{ + "driver": "custom", + "via": func() (session.Driver, error) { + return &CustomDriver{}, nil + }, + } +}, +``` + +[View Document](../the-basics/session.md#add-custom-session-driver) + +### Optimize Testing.Request methods + +Optimize the parameters of the `WithCookies` and `WithCookie` methods: + +```diff +-- WithCookies(cookies map[string]string) Request +++ WithCookies(cookies []*http.Cookie) Request + +-- WithCookie(key, value string) Request +++ WithCookie(cookie *http.Cookie) Request +``` + +### Optimize Carbon methods + +Previously, the `carbon.NewDateTime`, etc. methods return a struct instance, starting from v1.16, it returns a pointer, if you define the `carbon.DateTime` type, etc., you need to modify it to `*carbon.DateTime` etc. pointer type. + +### Optimize str.Snake methods + +The `str.Snake` method previously converted `userID` to `user_i_d`, starting from v1.16, it will be converted to `user_id`. + +### goravel/cloudinary is no longer maintained + +[goravel/cloudinary](https://github.com/goravel/cloudinary) is no longer maintained, please use [goravel/s3](https://github.com/goravel/s3) or other drivers instead. + +### Optimize Queue module configuration + +Before v1.15, the Redis driver of the Queue module was implemented using [RichardKnop/machinery](https://github.com/RichardKnop/machinery). Starting from v1.16, the Redis driver is officially supported in [goravel/redis](https://github.com/goravel/redis). + +You can still use the Machinery driver in v1.16, but it will be removed in v1.17, it is recommended to use the Redis driver. The following provides two upgrade methods: + +#### Continue using Machinery driver + +Modify the configuration in the `config/queue.go` file: + +```diff +// config/queue.go +"connections": map[string]any{ +... + "redis": map[string]any{ +-- "driver": "redis", +++ "driver": "machinery", + "connection": "default", + "queue": config.Env("REDIS_QUEUE", "default"), + }, +}, +``` + +#### Use Redis queue driver + +Modify the configuration in the `config/queue.go` file: + +```diff +// config/queue.go +import ( + "github.com/goravel/framework/contracts/queue" + redisfacades "github.com/goravel/redis/facades" +) + +"connections": map[string]any{ +... + "redis": map[string]any{ +-- "driver": "redis", +++ "driver": "custom", + "connection": "default", + "queue": config.Env("REDIS_QUEUE", "default"), +++ "via": func() (queue.Driver, error) { +++ return redisfacades.Queue("redis") // The ` + "`redis`" + ` value is the key of ` + "`connections`" + ` +++ }, + }, +}, +``` + +The new Redis queue driver and the original machinery queue driver tasks are stored in the same Redis, but use different queue names. Even if you switch to the new Redis queue driver, the framework will continue to read the original Machinery queue driver tasks until all tasks in Machinery are completed. At the same time, the new queue tasks are no longer written to the Machinery queue, but written to the new Redis queue, and consumed by the new Redis queue driver. To achieve seamless switching between two drivers. + +You can check the data of the two drivers in Redis to see if they are correctly written and consumed: + +```shell +redis-cli + +# Get all keys in Redis +keys + +# View Machinery queue driver data (replace {} with the value) +LRANGE {app_name}_queues:{queue_name} 0 -1 + +# View Redis queue driver data (replace {} with the value) +LRANGE {app_name}_queues:{connection}_{queue} 0 -1 +``` + +### Fix bcc and cc cannot be set expectly when sending mail + +goravel/framework: v1.16.1 + +Issue: [#737](https://github.com/goravel/goravel/issues/737) + +### Fix sending mail via queue returns incorrect error + +goravel/framework: v1.16.1 + +PR: [#1148](https://github.com/goravel/framework/pull/1148) + +### Fix the orm create events can be triggered when creating multiple records + +goravel/framework: v1.16.1 + +Issue: [#738](https://github.com/goravel/goravel/issues/738) + +### Fix the make:package command generates incorrect code + +goravel/framework: v1.16.1 + +Issue: [#743](https://github.com/goravel/goravel/issues/743) + +### Fix the path is incorrect when publishing package files + +goravel/framework: v1.16.1 + +Issue: [#749](https://github.com/goravel/goravel/issues/749) + +### Fix Transaction does not rollback when panic in closure + +goravel/framework: v1.16.3 + +Issue: [#762](https://github.com/goravel/goravel/issues/762) + +### Fix errors if adding or removing a column with a separate migration script + +goravel/framework: v1.16.3 + +goravel/postgres: v1.4.1 + +If adding or removing a column with a separate migration script and the application doesn't restart, the following two errors will occur: + +1. The DB facade will panic. +2. The Postgres driver will report an error: `cached plan must not change result type`. + +Issue: [#768](https://github.com/goravel/goravel/issues/768) + +### Fix the breaking change of Orm Select method + +goravel/framework: v1.16.3 + +There is a breaking change when upgrading the Orm Select method to v1.16 from v1.15. `Select` no longer supports `db.Raw()`, hence add the new `SelectRaw` method to avoid the breaking change. + +Issue: [#770](https://github.com/goravel/goravel/issues/770) + +### Fix commands cannot be run concurrently + +goravel/framework: v1.16.4 + +When running commands concurrently in the Schedule module, it may cause chaos or a panic due to concurrent writes. + +### Fix Queue cannot be shut down as expected + +goravel/framework: v1.16.5 + +Previously, when the Queue worker is running, sending a SIGTERM signal will shut down the worker immediately. Fix it to wait for the current job to complete before shutting down. + +Issue: [#807](https://github.com/goravel/goravel/issues/807) + +### Fix DB cache is not reset when fresh orm + +goravel/framework: v1.16.6 + +Fix the issue where the database connection cache was not properly reset when calling `facades.Orm().Fresh()`, which could lead to stale connections being used after ORM refresh. + +Issue: [#840](https://github.com/goravel/goravel/issues/840) + +### Fix log file rotation issue in daily logger + +goravel/framework: v1.16.6 + +Fix the issue where daily log rotation did not work correctly, as a new log file for the day was not created without restarting the application. + +Issue: [#847](https://github.com/goravel/goravel/issues/847) + +### Fix the paginate method will report an error when selecting and renaming only one column + +goravel/framework: v1.16.6 + +Fix the issue where the `Paginate` method would report an error when selecting and renaming only one column. The fix ensures that custom select columns do not interfere with count operations during pagination. + +Issue: [#842](https://github.com/goravel/goravel/issues/842) + +### Fix Cursor cannot scan json column + +goravel/framework: v1.16.6 + +Fixed an issue where the database cursor could not scan JSON columns by enhancing the row scanning functionality. This change adds support for properly handling JSON columns and custom types, with new decode hooks for automatic JSON-to-Go conversions into `map[string]any`, slices (`[]string`, `[]int`), and custom structs. + +Issue: [#818](https://github.com/goravel/goravel/issues/818) + +### Fix Distinct has no effect when using with Count + +goravel/framework: v1.16.7 + +Fix the issue where using `Distinct` in combination with `Count` did not produce the expected distinct count results. The fix ensures that the `Distinct` clause is correctly applied when counting records. + +Issue: [#856](https://github.com/goravel/goravel/issues/856) + +### DB.Insert can not operate nil columns as expected + +goravel/framework: v1.16.7 + +Fix the issue where `facades.DB().Insert()` could not handle nil columns as expected. + +```go +type Product struct { + Model + SoftDeletes + Name string `db:"name"` + Weight *int `db:"weight"` // Pointer + Height *int `db:"height"` +} + +// The Weight will be ignored if the first data doesn't contain Weight +facades.DB().Table("products").Insert([]Product{ + {Name: "count_product1"}, + {Name: "count_product2", Weight: convert.Pointer(1)}, +}) + +// Normal +facades.DB().Table("products").Insert([]Product{ + {Name: "count_product2", Weight: convert.Pointer(1)}, + {Name: "count_product1"}, +}) +``` + +Issue: [#858](https://github.com/goravel/goravel/issues/858) + +### Fix incorrect orm nested relationships load + +goravel/framework: v1.16.7 + +The Orm cannot handle nested associations when using `Load()`. + +```go +facades.Orm().Query().Load(&model, "Author.Contacts") +``` + +### Fix delay task issue when queue concurrency is greater than 1 + +goravel/framework: v1.16.8 + +goravel/redis: v1.4.1 + +When the queue worker concurrency is greater than 1, delay tasks will be executed several times. This is because multiple workers may pick up the same delayed task when it becomes available. Now a distributed lock is used to ensure that only one worker can execute the delayed task at a time. From 38e84e4524f8cdd498714f716d83e3439764b4db Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:04 +0800 Subject: [PATCH 060/163] New translations v1.2.md (Uzbek) [skip ci] Update translations (Uzbek) v1.2.md --- uz_UZ/upgrade/v1.2.md | 74 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 uz_UZ/upgrade/v1.2.md diff --git a/uz_UZ/upgrade/v1.2.md b/uz_UZ/upgrade/v1.2.md new file mode 100644 index 000000000..c4f65fc12 --- /dev/null +++ b/uz_UZ/upgrade/v1.2.md @@ -0,0 +1,74 @@ +# Upgrading To v1.2 From v1.1 + +## High Impact Changes + +- [Updating Dependencies](#updating-dependencies) +- [Auth support context](#auth-support-context) + +## Upgrade Guide + +**Estimated Upgrade Time: 1 Minutes** + +### Updating Dependencies + +**Likelihood Of Impact: High** + +Update dependencies in the `go.mod` file: + +```go +github.com/goravel/framework v1.2.1 +``` + +### Auth Support Context + +**Likelihood Of Impact: High** + +``` +// Old +facades.Auth.Parse(token string) error + +// New +facades.Auth.Parse(ctx http.Context, token string) error +``` + +``` +// Old +facades.Auth.User(ctx http.Context, user interface{}) error + +// New +facades.Auth.User(ctx http.Context, user interface{}) error +``` + +``` +// Old +facades.Auth.facades.Auth.Login(user interface{}) (token string, err error) + +// New +facades.Auth.facades.Auth.Login(ctx http.Context, user interface{}) (token string, err error) +``` + +``` +// Old +facades.Auth.LoginUsingID(id interface{}) (token string, err error) + +// New +facades.Auth.LoginUsingID(ctx http.Context, id interface{}) (token string, err error) +``` + +``` +// Old +facades.Auth.Refresh() (token string, err error) + +// New +facades.Auth.Refresh(ctx http.Context) (token string, err error) +``` + +``` +// Old +facades.Auth.Logout() error + +// New +facades.Auth.Logout(ctx http.Context) error +``` + +For detail [facades.Auth](../security/authentication.md)。 From 68c69d8045649a0818598cb28395389e12514d4e Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:04 +0800 Subject: [PATCH 061/163] New translations v1.3.md (Uzbek) [skip ci] Update translations (Uzbek) v1.3.md --- uz_UZ/upgrade/v1.3.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 uz_UZ/upgrade/v1.3.md diff --git a/uz_UZ/upgrade/v1.3.md b/uz_UZ/upgrade/v1.3.md new file mode 100644 index 000000000..f6dcca3ce --- /dev/null +++ b/uz_UZ/upgrade/v1.3.md @@ -0,0 +1,39 @@ +# Upgrading To v1.3 From v1.2 + +## Medium Impact Changes + +- [Add CORS Configuration](#add-cors-configuration) + +## Low Impact Changes + +- [Add Dockerfile](#add-dockerfile) + +## Upgrade Guide + +**Estimated Upgrade Time: 1 Minutes** + +### Updating Dependencies + +**Likelihood Of Impact: High** + +Update dependencies in the `go.mod` file: + +```go +github.com/goravel/framework v1.3.1 +``` + +### Add CORS Configuration + +**Likelihood Of Impact: Medium** + +[config/cors.go](https://github.com/goravel/goravel/blob/v1.3.1/config/cors.go) + +[For detail](../the-basics/routing.md#cross-origin-resource-sharing-cors) + +### Add Dockerfile + +**Likelihood Of Impact: Low** + +[Dockerfile](https://github.com/goravel/goravel/blob/v1.3.1/Dockerfile) + +[For detail](../getting-started/compile.md#docker) From b1528b43252d1be20810a9dcd316c85f61692594 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:05 +0800 Subject: [PATCH 062/163] New translations v1.4.md (Uzbek) [skip ci] Update translations (Uzbek) v1.4.md --- uz_UZ/upgrade/v1.4.md | 62 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 uz_UZ/upgrade/v1.4.md diff --git a/uz_UZ/upgrade/v1.4.md b/uz_UZ/upgrade/v1.4.md new file mode 100644 index 000000000..dc5783c12 --- /dev/null +++ b/uz_UZ/upgrade/v1.4.md @@ -0,0 +1,62 @@ +# Upgrading To v1.4 From v1.3 + +[[toc]] + +## High Impact Changes + +- [Optimize Grpc Module](#optimize-grpc-module) +- [Optimize Route Register](#optimize-route-register) + +## Low Impact Changes + +- [Add http.Context Method](#add-http-context-method) +- [Add Request Method](#add-request-method) + +## Upgrade Guide + +**Estimated Upgrade Time: 1 Minutes** + +### Updating Dependencies + +**Likelihood Of Impact: High** + +Update dependencies in the `go.mod` file: + +```go +github.com/goravel/framework v1.4.0 +``` + +### Optimize Grpc Module + +**Likelihood Of Impact: High** + +1. Add [app/grpc/kernel.go](https://github.com/goravel/goravel/blob/v1.4.0/app/grpc/kernel.go) file; +2. Add [app/grpc/interceptors](https://github.com/goravel/goravel/tree/v1.4.0/app/grpc/interceptors) folder; +3. Add [config/grpc.go](https://github.com/goravel/goravel/blob/v1.4.0/config/grpc.go) file; +4. Add [routes/grpc.go](https://github.com/goravel/goravel/blob/v1.4.0/routes/grpc.go) file; +5. Add register interceptor logic in [app/providers/grpc_service_provider.go](https://github.com/goravel/goravel/blob/v1.4.0/app/providers/grpc_service_provider.go); +6. Remove `grpc_host` in [config/app.go](https://github.com/goravel/goravel/blob/v1.4.0/config/app.go); + +[For Detail](../the-basics/grpc.md) + +### Optimize Route Register + +**Likelihood Of Impact: High** + +Move `routes.Web()` to `Boot()` from `Register()` in [app/providers/route_service_provider.go](https://github.com/goravel/goravel/blob/v1.4.0/app/providers/route_service_provider.go); + +### Add http.Context Method + +**Likelihood Of Impact: Low** + +Add `ctx.Context()` Method. + +[For Detail](../the-basics/request.md#get-context) + +### Add Request Method + +**Likelihood Of Impact: Low** + +Add `ctx.Request().AbortWithStatusJson` method. + +[For Detail](../the-basics/request.md#abort-request) From b71a190b052d6119ab543ff88efbc2fc45dfe05d Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:06 +0800 Subject: [PATCH 063/163] New translations v1.5.md (Uzbek) [skip ci] Update translations (Uzbek) v1.5.md --- uz_UZ/upgrade/v1.5.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 uz_UZ/upgrade/v1.5.md diff --git a/uz_UZ/upgrade/v1.5.md b/uz_UZ/upgrade/v1.5.md new file mode 100644 index 000000000..397202647 --- /dev/null +++ b/uz_UZ/upgrade/v1.5.md @@ -0,0 +1,30 @@ +# Upgrading To v1.5 From v1.4 + +[[toc]] + +## High Impact Changes + +- [Add File Storage Module](#add-file-storage-module) + +## Upgrade Guide + +**Estimated Upgrade Time: 1 Minutes** + +### Updating Dependencies + +**Likelihood Of Impact: High** + +Update dependencies in the `go.mod` file: + +```go +github.com/goravel/framework v1.5.0 +``` + +### Add File Storage Module + +**Likelihood Of Impact: High** + +1. Add [config/filesystems.go](https://github.com/goravel/goravel/blob/v1.5.0/config/filesystems.go) file; +2. Add `&filesystem.ServiceProvider{}` to the `providers` item in the [config/app.go](https://github.com/goravel/goravel/blob/v1.5.0/config/app.go) file; + +[For Detail](../digging-deeper/filesystem.md) From 637a2e8299b06ff82dd526c325050188e8a6234c Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:07 +0800 Subject: [PATCH 064/163] New translations v1.6.md (Uzbek) [skip ci] Update translations (Uzbek) v1.6.md --- uz_UZ/upgrade/v1.6.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 uz_UZ/upgrade/v1.6.md diff --git a/uz_UZ/upgrade/v1.6.md b/uz_UZ/upgrade/v1.6.md new file mode 100644 index 000000000..fc8f438aa --- /dev/null +++ b/uz_UZ/upgrade/v1.6.md @@ -0,0 +1,30 @@ +# Upgrading To v1.6 From v1.5 + +[[toc]] + +## High Impact Changes + +- [Add Authorization Module](#add-authorization-module) + +## Upgrade Guide + +**Estimated Upgrade Time: 1 Minutes** + +### Updating Dependencies + +**Likelihood Of Impact: High** + +Update dependencies in the `go.mod` file: + +```go +github.com/goravel/framework v1.6.3 +``` + +### Add Authorization Module + +**Likelihood Of Impact: High** + +1. Add [app/providers/auth_service_provider.go](https://github.com/goravel/goravel/blob/v1.6.0/app/providers/auth_service_provider.go) file; +2. Add `&providers.AuthServiceProvider{}` to the `providers` item in the [config/app.go](https://github.com/goravel/goravel/blob/v1.6.0/config/app.go) file; + +[For Detail](../security/authorization.md) From e449166162847f76e1c31e56ee2864a64615b3db Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:08 +0800 Subject: [PATCH 065/163] New translations v1.7.md (Uzbek) [skip ci] Update translations (Uzbek) v1.7.md --- uz_UZ/upgrade/v1.7.md | 72 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 uz_UZ/upgrade/v1.7.md diff --git a/uz_UZ/upgrade/v1.7.md b/uz_UZ/upgrade/v1.7.md new file mode 100644 index 000000000..f63e363f1 --- /dev/null +++ b/uz_UZ/upgrade/v1.7.md @@ -0,0 +1,72 @@ +# Upgrading To v1.7 From v1.6 + +[[toc]] + +## High Impact Changes + +- [Add Validation Module(v1.7.0)](#add-validation-module) +- [Fix request template BUG(v1.7.1)](#fix-request-template-bug) +- [Fix Validation module BUG(v1.7.2)](#fix-Validation-module-big) +- [Fix Auth module BUG(v1.7.3)](#fix-auth-module-bug) + +## Low Impact Changes + +- [Optimize the queue name of the queue module(v1.7.2)](#optimize-the-queue-name-of-the-queue-module) + +## Upgrade Guide + +**Estimated Upgrade Time: 1 Minutes** + +### Updating Dependencies + +**Likelihood Of Impact: High** + +Update dependencies in the `go.mod` file: + +```go +github.com/goravel/framework v1.7.3 +``` + +### Add Validation module + +**Likelihood Of Impact: High** + +Version: v1.7.0 + +1. Add [app/providers/validation_service_provider.go](https://github.com/goravel/goravel/blob/v1.7.0/app/providers/validation_service_provider.go) file; +2. Add `&validation.ServiceProvider{}`, `&providers.ValidationServiceProvider{},` to the `providers` item in the [config/app.go](https://github.com/goravel/goravel/blob/v1.7.0/config/app.go) file; + +[For Detail](../the-basics/validation.md) + +### Fix request template BUG + +**Likelihood Of Impact: High** + +Version: v1.7.1 + +1. Fix import path BUG of the request template that created by `go run . artisan make:request Test`; + +### Fix Validation module BUG + +**Likelihood Of Impact: High** + +Version: v1.7.2 + +1. Fix the BUG that does not take effect when the `facades.Validation` module registers multiple custom Rule; + +### Optimize the queue name of the queue module + +**Likelihood Of Impact: Low** + +Version: v1.7.2 + +1. Add a prefix to the queue name of the `facades.Queue` module during actual execution, in order to distinguish between multiple projects, the prefix rule: ${app_name}_queues:${queue}; +2. Implicit optimization, you don't need to modify any code; + +### Fix Auth module BUG + +**Likelihood Of Impact: High** + +Version: v1.7.3 + +1. Fix the BUG that calling `facades.Auth.User` method returns `Unknown column` error when the primary key of user table is `string` type; From 9bdfdda3e67d42c8f2484acaecde0871c20caaf4 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:09 +0800 Subject: [PATCH 066/163] New translations v1.8.md (Uzbek) [skip ci] Update translations (Uzbek) v1.8.md --- uz_UZ/upgrade/v1.8.md | 178 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 uz_UZ/upgrade/v1.8.md diff --git a/uz_UZ/upgrade/v1.8.md b/uz_UZ/upgrade/v1.8.md new file mode 100644 index 000000000..c08729a56 --- /dev/null +++ b/uz_UZ/upgrade/v1.8.md @@ -0,0 +1,178 @@ +# Upgrading To v1.8 From v1.7 + +[[toc]] + +## Exciting New Features 🎉 + +- [Add model association for Orm(1.8.0)](#add-model-association-for-orm) + +## Enhancements 🚀 + +- [Add methods for Request(1.8.0)](#add-methods-for-request) +- [Add methods for Response(1.8.0)](#add-methods-for-response) +- [Optimize database migrate(1.8.0)](#optimize-database-migrate) +- [Route supports HTTPS(1.8.3)](#route-supports-https) + +## Breaking Changes 🛠 + +- [Optimize import order(1.8.0)](#optimize-import-order) +- [mock.Validator change name(1.8.0)](#mock-validator-change-Name) +- [support.Mysql change name(1.8.0)](#support-mysql-change-name) +- [database.NewGormInstance is about to be deprecated(1.8.0)](#database-newgorminstance-is-about-to-be-deprecated) + +## Bug Fixes 🐛 + +- [Fix Orm concurrency safety issue(1.8.1)](#fix-Orm-concurrency-safety-issue) +- [Fix Mail module can't send mail by 25 and 465 ports(1.8.2)](#fix-mail-module-can-t-send-mail-by-25-and-465-ports) + +## Upgrade Guide + +**Estimated Upgrade Time: 1 Minutes** + +### Updating Dependencies + +Update dependencies in the `go.mod` file: + +``` +go get -u github.com/goravel/framework@v1.8.3 +``` + +### Add model association for Orm + +Version: v1.8.0 + +Add methods for Orm, to handle model association: + +| Method | Action | +| ----------- | --------------------------------------------------------------------------------------------------------------- | +| Association | [Association](../orm/relationships.md#querying-associations) | +| DB | [Generic Database Interface sql.DB](../orm/getting-started.md#generic-database-interface-sqldb) | +| Load | [Lazy Eager Loading](../orm/relationships.md#lazy-eager-loading) | +| LoadMissing | [Lazy Eager Loading(not exist)](../orm/relationships.md#lazy-eager-loading) | +| Omit | [Omit associations](../orm/relationships.md#create-or-update-associations) | +| With | [Eager Loading](../orm/relationships.md#Eager-Loading) | + +### Add methods for Request + +Version: v1.8.0 + +Add methods for `ctx.Request()`, to enrich the format of `Query` parameters: + +| Method | Action | +| ------------ | ------------------------------------------------------------------------------------------- | +| `QueryArray` | [Get the array parameters](../the-basics/request.md#Retrieving-Input-From-The-Query-String) | +| `QueryMap` | [Get the map parameters](../the-basics/request.md#Retrieving-Input-From-The-Query-String) | + +### Add-methods-for-Response + +Version: v1.8.0 + +Add `Origin` method to `ctx.Response()`, you can get all information of `Response` in the HTTP middleware. + +[Detail](../the-basics/response.md#Get-Response) + +### Optimize import order + +Version: v1.8.0 + +The import order in the `bootstrap/app.go` file change to: + +```go +package bootstrap + +import ( + "github.com/goravel/framework/foundation" + + "goravel/config" +) +``` + +[The File](https://github.com/goravel/goravel/blob/v1.8.0/bootstrap/app.go) + +### Optimize database migrate + +Version: v1.8.0 + +Run the command that generate the migrate file: `go run . artisan make:migration create_users_table`, the corresponding migration file will be generated based on the default database driver currently in use(`facades.Config.GetString("database.default")`). + +### mock.Validator Change Name + +Version: v1.8.0 + +If you use `mock.Validator` to write unit tests, the following modifications are required: + +``` +import "github.com/goravel/framework/testing/mock" + +mock.Validator + +// Modify to + +import "github.com/goravel/framework/testing/mock" + +mock.Validation +``` + +[Detail](../testing/mock.md#Mock-facades.Validation) + +### support.Mysql Change Name + +Version: v1.8.0 + +If you use framework constants such as `support.Mysql` to judge the database driver, you need to make the following modifications: + +```go +import "github.com/goravel/framework/database/support" + +support.Mysql +support.Postgresql +support.Sqlite +support.Sqlserver + +// Modify to + +import "github.com/goravel/framework/contracts/database/orm" + +orm.Mysql +orm.Postgresql +orm.Sqlite +orm.Sqlserver +``` + +The new constants such as `orm.Mysql` are of type `orm.Driver` and can be converted to a string type using the `orm.Mysql.String()` method. + +### database.NewGormInstance is about to be deprecated + +Version: v1.8.0 + +The `database.NewGormInstance` method will be deprecated in v1.9.0 version, it can be used in current version, if you use the method to get the `gorm` instance, the following modifications are required: + +```go +import "github.com/goravel/framework/database" + +gorm, err := database.NewGormInstance(connection) + +// Modify to + +import "github.com/goravel/framework/database/gorm" + +gorm, err := gorm.New(connection) +``` + +### Fix Orm concurrency safety issue + +Version: v1.8.1 + +When high concurrent access, reading `facades.Orm` for the first time may return nil. + +### Fix Mail module can't send mail by 25 and 465 ports + +Version: v1.8.2 + +You can send mail by 25, 465, 587 ports now. + +### Route supports HTTPS + +Version: v1.8.3 + +`facades.Route` Add `RunTLS` method,support start HTTPS server, [For Detail](../the-basics/routing.md#start-https-server). From bfa8790d948ed78aa9b50e5b29e8cebaec73c042 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:10 +0800 Subject: [PATCH 067/163] New translations v1.9.md (Uzbek) [skip ci] Update translations (Uzbek) v1.9.md --- uz_UZ/upgrade/v1.9.md | 139 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 uz_UZ/upgrade/v1.9.md diff --git a/uz_UZ/upgrade/v1.9.md b/uz_UZ/upgrade/v1.9.md new file mode 100644 index 000000000..91160c11e --- /dev/null +++ b/uz_UZ/upgrade/v1.9.md @@ -0,0 +1,139 @@ +# Upgrading To v1.9 From v1.8 + +[[toc]] + +## Enhancements 🚀 + +- [Add database read-write separation(1.9.0)](#add-database-read-write-separation) +- [Add database pool configuration(1.9.0)](#add-database-pool-configuration) +- [Custom .env path(1.9.0)](#custom--env-path) +- [Cache add memory driver(1.9.0)](#cache-add-memory-driver) +- [Orm add Paginate method(1.9.0)](#orm-add-paginate-method) +- [Add make command(1.9.0)](#add-make-command) +- [Add new methods for Response(1.9.0)](#add-new-methods-for-Response) + +## Breaking Changes 🛠 + +- [Add return for Request PrepareForValidation method(1.9.0)](#add-return-for-request-prepareforvalidation-method) + +## Bug Fixes 🐛 + +- [File gets the wrong file type(1.9.0)](#file-gets-the-wrong-file-type) +- [Fix template error on make:event and make:listener command(1.9.0)](#fix-template-error-on-make-event-and-make-listener-command) +- [Fix some types cannot obtain suffixes when save file(1.9.1)](#fix-some-types-cannot-obtain-suffixes-when-save-file) + +## Dependency Updates ⬆️ + +- build(deps): bump github.com/gin-gonic/gin from v1.7.3 to v1.8.2 + +## Upgrade Guide + +**Estimated Upgrade Time: 10 Minutes** + +### Updating Dependencies + +Update dependencies in the `go.mod` file: + +``` +go get -u github.com/goravel/framework@v1.9.0 +``` + +### Add database read-write separation + +Version: v1.9.0 + +Database supports read-write separation,[For Detail](../orm/getting-started.md#read--write-connections). + +### Add database pool configuration + +Version: v1.9.0 + +Add pool configuration for the database configuration file: `config/database.go`, [For Detail](https://github.com/goravel/goravel/blob/v1.9.x/config/database.go). + +### Custom .env path + +Version: v1.9.0 + +``` +// Develop +go run . --env=../.env + +// Compiled +./main --env=../.env +``` + +### Cache add memory driver + +Version: v1.9.0 + +`config/cache.go` add `memory` configuration: + +``` +"stores": map[string]any{ + // New + "memory": map[string]any{ + "driver": "memory", + }, +}, +``` + +[For Detail](https://github.com/goravel/goravel/blob/v1.9.x/config/cache.go) + +### Orm add Paginate method + +Version: v1.9.0 + +`facades.Orm` add `Paginate` method, [For detail](../orm/getting-started.md#Paginate). + +### Add make command + +Version: v1.9.0 + +``` +// Create controller +go run . artisan make:controller UserController + +// Create middleware +go run . artisan make:middleware Cors + +// Create model +go run . artisan make:model User +``` + +### Add new methods for Response + +Version: v1.9.0 + +| Method | Action | +| -------- | -------------------------------------------------------- | +| Data | [Custom return](../the-basics/response.md#custom-return) | +| Redirect | [Redirect](../the-basics/response.md#redirect) | + +### Add return for Request PrepareForValidation method + +Version: v1.9.0 + +If you are using [PrepareForValidation method in Validation](../the-basics/validation.md#format-data-before-validation), please add a return value: `PrepareForValidation(data validation.Data) error`. + +### File gets the wrong file type + +Version: v1.9.0 + +Fix the problem that `.docx`, `.xlsx`, etc. are incorrectly identified as `.zip`. + +### Fix template error on make:event and make:listener command + +Version: v1.9.0 + +`import "github.com/goravel/framework/contracts/events"` 改为 `import "github.com/goravel/framework/contracts/event"` + +### Fix some types cannot obtain suffixes when save file + +Version: v1.9.1 + +Some types cannot obtain suffixes through the code shown below: + +```go +file, err := ctx.Request().File() +file.Store("upload") +``` From 3a745fb11095dd2cf6ea27b4edb6434d267cf960 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:11 +0800 Subject: [PATCH 068/163] New translations en.ts (Uzbek) [skip ci] Update translations (Uzbek) en.ts --- .vitepress/config/uz_UZ.ts | 295 +++++++++++++++++++++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 .vitepress/config/uz_UZ.ts diff --git a/.vitepress/config/uz_UZ.ts b/.vitepress/config/uz_UZ.ts new file mode 100644 index 000000000..4dafc2d60 --- /dev/null +++ b/.vitepress/config/uz_UZ.ts @@ -0,0 +1,295 @@ +import { defineConfig, type DefaultTheme } from 'vitepress'; +export const config = defineConfig({ + lang: 'en-US', + description: 'Goravel is a web application framework with complete functions and excellent scalability. As a starting scaffolding to help Gopher quickly build their own applications.', + themeConfig: { + nav: nav(), + sidebar: [{ + text: 'Prologue', + base: '/prologue/', + items: sidebarPrologue() + }, { + text: 'Upgrade', + base: '/upgrade/', + items: sidebarUpgrade() + }, { + text: 'Getting Started', + base: '/getting-started/', + items: sidebarGettingStarted() + }, { + text: 'Architecture Concepts', + base: '/architecture-concepts/', + items: sidebarFoundation() + }, { + text: 'The Basics', + base: '/the-basics/', + items: sidebarBasic() + }, { + text: 'Digging Deeper', + base: '/digging-deeper/', + items: sidebarAdvanced() + }, { + text: 'Security', + base: '/security/', + items: sidebarSecurity() + }, { + text: 'Database', + base: '/database/', + items: sidebarDatabase() + }, { + text: 'ORM', + base: '/orm/', + items: sidebarOrm() + }, { + text: 'Testing', + base: '/testing/', + items: sidebarTesting() + }], + editLink: { + pattern: 'https://github.com/goravel/docs/edit/master/:path', + text: 'Edit this page on GitHub' + }, + footer: { + message: 'Released under the MIT License', + copyright: `Copyright © 2021-${new Date().getFullYear()} Goravel` + }, + docFooter: { + prev: 'Previous page', + next: 'Next page' + }, + outline: { + label: 'On this page' + }, + lastUpdated: { + text: 'Last updated', + formatOptions: { + dateStyle: 'short', + timeStyle: 'medium' + } + }, + langMenuLabel: 'Change language', + returnToTopLabel: 'Return to top', + sidebarMenuLabel: 'Menu', + darkModeSwitchLabel: 'Appearance', + lightModeSwitchTitle: 'Switch to light theme', + darkModeSwitchTitle: 'Switch to dark theme', + skipToContentLabel: 'Skip to content' + } +}); +function nav(): DefaultTheme.NavItem[] { + return [{ + text: 'Quickstart', + link: '/getting-started/installation', + activeMatch: '/getting-started/' + }, { + text: 'Video Tutorials', + link: 'https://www.youtube.com/playlist?list=PL40Xne4u-oXJ0Z5uFiPWHqIMvzZaG_BDf' + }, { + text: 'Versions', + items: [{ + text: "v1.17 (Eng so'nggi)", + link: "" + }, { + text: 'v1.16', + link: 'https://v116.goravel.dev/' + }] + }, { + text: 'Translate', + link: '/prologue/contributions#add-a-new-language' + }]; +} +function sidebarGettingStarted(): DefaultTheme.SidebarItem[] { + return [{ + text: 'Installation', + link: 'installation' + }, { + text: 'Configuration', + link: 'configuration' + }, { + text: 'Directory Structure', + link: 'directory-structure' + }, { + text: 'Compile', + link: 'compile' + }, { + text: 'Excellent Packages', + link: 'packages' + }]; +} +function sidebarPrologue(): DefaultTheme.SidebarItem[] { + return [{ + text: 'Release Notes', + link: 'releases' + }, { + text: 'Contribution Guide', + link: 'contributions' + }, { + text: 'Compare With Laravel', + link: 'compare-with-laravel' + }, { + text: 'Privacy Policy', + link: 'privacy' + }]; +} +function sidebarUpgrade(): DefaultTheme.SidebarItem[] { + return [{ + text: 'Upgrading To v1.17 From v1.16', + link: 'v1.17' + }, { + text: 'Upgrading To v1.16 From v1.15', + link: 'v1.16' + }, { + text: 'History', + link: 'history' + }]; +} +function sidebarFoundation(): DefaultTheme.SidebarItem[] { + return [{ + text: 'Lifecycle', + link: 'request-lifecycle' + }, { + text: 'Service Container', + link: 'service-container' + }, { + text: 'Service Providers', + link: 'service-providers' + }, { + text: 'Facades', + link: 'facades' + }]; +} +function sidebarBasic(): DefaultTheme.SidebarItem[] { + return [{ + text: 'Routing', + link: 'routing' + }, { + text: 'Middleware', + link: 'middleware' + }, { + text: 'Controllers', + link: 'controllers' + }, { + text: 'Requests', + link: 'request' + }, { + text: 'Responses', + link: 'response' + }, { + text: 'Views', + link: 'views' + }, { + text: 'Grpc', + link: 'grpc' + }, { + text: 'Session', + link: 'session' + }, { + text: 'Validation', + link: 'validation' + }, { + text: 'Logging', + link: 'logging' + }]; +} +function sidebarAdvanced(): DefaultTheme.SidebarItem[] { + return [{ + text: 'Artisan Console', + link: 'artisan-console' + }, { + text: 'Cache', + link: 'cache' + }, { + text: 'Event', + link: 'event' + }, { + text: 'File Storage', + link: 'filesystem' + }, { + text: 'Mail', + link: 'mail' + }, { + text: 'Queues', + link: 'queues' + }, { + text: 'Task Scheduling', + link: 'task-scheduling' + }, { + text: 'Localization', + link: 'localization' + }, { + text: 'Package Development', + link: 'package-development' + }, { + text: 'Color Output', + link: 'color' + }, { + text: 'Processes', + link: 'processes' + }, { + text: 'Strings', + link: 'strings' + }, { + text: 'Helpers', + link: 'helpers' + }, { + text: 'HTTP Client', + link: 'http-client' + }, { + text: 'Pluralization', + link: 'pluralization' + }]; +} +function sidebarSecurity(): DefaultTheme.SidebarItem[] { + return [{ + text: 'Authentication', + link: 'authentication' + }, { + text: 'Authorization', + link: 'authorization' + }, { + text: 'Encryption', + link: 'encryption' + }, { + text: 'Hashing', + link: 'hashing' + }]; +} +function sidebarDatabase(): DefaultTheme.SidebarItem[] { + return [{ + text: 'Getting Started', + link: 'getting-started' + }, { + text: 'Query Builder', + link: 'queries' + }, { + text: 'Migrations', + link: 'migrations' + }, { + text: 'Seeding', + link: 'seeding' + }]; +} +function sidebarOrm(): DefaultTheme.SidebarItem[] { + return [{ + text: 'Getting Started', + link: 'getting-started' + }, { + text: 'Relationships', + link: 'relationships' + }, { + text: 'Factories', + link: 'factories' + }]; +} +function sidebarTesting(): DefaultTheme.SidebarItem[] { + return [{ + text: 'Getting Started', + link: 'getting-started' + }, { + text: 'HTTP Tests', + link: 'http-tests' + }, { + text: 'Mock', + link: 'mock' + }]; +} \ No newline at end of file From 2b1f018307a221f83ac0b1e03225f99853d0185c Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:12 +0800 Subject: [PATCH 069/163] New translations releases.md (Uzbek) [skip ci] Update translations (Uzbek) releases.md --- uz_UZ/prologue/releases.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 uz_UZ/prologue/releases.md diff --git a/uz_UZ/prologue/releases.md b/uz_UZ/prologue/releases.md new file mode 100644 index 000000000..9b8aa2624 --- /dev/null +++ b/uz_UZ/prologue/releases.md @@ -0,0 +1,17 @@ +# Release Notes + +## Versioning Scheme + +Goravel releases are released every half of year (~Q1 and ~Q3), while patch releases may be released as often as every week. Patch releases should never contain breaking changes. + +## Support Policy + +For all Goravel releases, bug fixes are provided for 12 months. + +| Version | Golang | Release | Bug Fixes Until | +| -------------------- | -------------------- | ------------ | --------------- | +| 1.18 | 1.25 | Q3 2026 | Q3 2027 | +| 1.17 | 1.24 | Feb 3, 2026 | Feb 3, 2027 | +| 1.16 | 1.23 | Jul 20, 2025 | Jul 20, 2026 | +| 1.15 | 1.22 | Dec 31, 2024 | Dec 31, 2025 | +| 1.14 | 1.21 | Jun 8, 2024 | Jun 8, 2025 | From 3befd740041f824da311d1669467175518833562 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:13 +0800 Subject: [PATCH 070/163] New translations pluralization.md (Uzbek) [skip ci] Update translations (Uzbek) pluralization.md --- uz_UZ/digging-deeper/pluralization.md | 120 ++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 uz_UZ/digging-deeper/pluralization.md diff --git a/uz_UZ/digging-deeper/pluralization.md b/uz_UZ/digging-deeper/pluralization.md new file mode 100644 index 000000000..59c437fcd --- /dev/null +++ b/uz_UZ/digging-deeper/pluralization.md @@ -0,0 +1,120 @@ +# Pluralization + +[[toc]] + +## Introduction + +Strings are important for any web application. Goravel provides simple utilities to convert words between singular +and plural forms. It supports **English** by default, but you can add other languages or custom rules easily. + +## Basic Usage + +You can use the `Plural` and `Singular` methods from the `pluralizer` package. These handle most English words automatically. + +```go +import "github.com/goravel/framework/support/pluralizer" + +// Pluralize words +pluralizer.Plural("goose") // "geese" +pluralizer.Plural("car") // "cars" + +// Singularize words +pluralizer.Singular("geese") // "goose" +pluralizer.Singular("cars") // "car" +``` + +## Custom Rules + +Sometimes the default rules are not enough for specific words. Goravel lets you add your own rules to handle these cases. + +:::warning +Adding rules changes how pluralization works globally. You should do this when your application starts, +like in the `Boot` method of a Service Provider. +::: + +### Irregular Words + +If a word has a unique plural form, you can register it as an "irregular" word. This handles changes in both directions. + +```go +import ( + "github.com/goravel/framework/support/pluralizer" + "github.com/goravel/framework/support/pluralizer/rules" +) + +// Register that "mouse" becomes "mice" +pluralizer.RegisterIrregular("english", rules.NewSubstitution("mouse", "mice")) +``` + +### Uninflected Words + +Some words like "fish" or "media" do not change form or are always plural. You can mark these as "uninflected" +so the pluralizer skips them. + +```go +// "sheep" stays "sheep" in singular and plural +pluralizer.RegisterUninflected("english", "sheep") + +// "media" is always treated as plural +pluralizer.RegisterPluralUninflected("english", "media") + +// "data" is always treated as singular +pluralizer.RegisterSingularUninflected("english", "data") +``` + +## Language Support + +Goravel uses "english" by default, but you can switch languages or add new ones if you need to. + +### Switching Languages + +If you have other languages registered, you can switch the active one using `UseLanguage`. + +```go +if err := pluralizer.UseLanguage("spanish"); err != nil { + panic(err) +} + +// Get the current language name +name := pluralizer.GetLanguage().Name() +``` + +### Adding New Languages + +To add a language, you need to implement the `Language` interface. This defines how words change in that language. + +```go +import "github.com/goravel/framework/contracts/support/pluralizer" + +type Language interface { + Name() string + SingularRuleset() pluralizer.Ruleset + PluralRuleset() pluralizer.Ruleset +} +``` + +After implementing your language struct, register it and set it as active. + +```go +import "github.com/goravel/framework/support/pluralizer" + +func init() { + // Register the new language + if err := pluralizer.RegisterLanguage(&MyCustomLanguage{}); err != nil { + panic(err) + } + + // Set it as active + _ = pluralizer.UseLanguage("my_custom_language") +} +``` + +## Supported Languages + +Currently, the pluralizer supports the following languages out of the box: + +| Language | Code | Source | +| :------- | :-------- | :----------------------------------------------------------------------------------------- | +| English | `english` | [View Source](https://github.com/goravel/framework/tree/master/support/pluralizer/english) | + +_More languages will be added in future releases. You are welcome to contribute new languages via Pull Request._ \ No newline at end of file From 92f624395f83d593c1fa0276f2b6e8cea92717ed Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:14 +0800 Subject: [PATCH 071/163] New translations processes.md (Uzbek) [skip ci] Update translations (Uzbek) processes.md --- uz_UZ/digging-deeper/processes.md | 419 ++++++++++++++++++++++++++++++ 1 file changed, 419 insertions(+) create mode 100644 uz_UZ/digging-deeper/processes.md diff --git a/uz_UZ/digging-deeper/processes.md b/uz_UZ/digging-deeper/processes.md new file mode 100644 index 000000000..a81d5ac28 --- /dev/null +++ b/uz_UZ/digging-deeper/processes.md @@ -0,0 +1,419 @@ +# Processes + +[[toc]] + +## Introduction + +Goravel provides an expressive and elegant API around Go's standard `os/exec` package, allowing you to invoke external commands from your application seamlessly. By default, Go's process handling can be verbose; Goravel's `Process` facade simplifies this common task, offering a fluent interface for executing commands, handling output, and managing asynchronous processes. + +## Invoking Processes + +### Running Processes + +To run a process, you can use the `Run` or `Start` methods. The `Run` method will execute the command and wait for it to finish, while the `Start` method triggers the process asynchronously and returns control immediately. + +Here is how you execute a blocking command: + +```go +import ( + "fmt" + + "goravel/app/facades" +) + +func main() { + result := facades.Process().Run("echo", "Hello, World!") + if result.Failed() { + panic(result.Error()) + } + + fmt.Println(result.Output()) +} +``` + +If you want to run a string command directly (without splitting it into arguments), you can pass the command to `Run` as a single string, `/bin/sh -c` (Linux/macOS) or `cmd /C` (Windows) will be used under the hood. Notice, the mechanism can only be triggered when the string command contains spaces or `&`, `|`, `-`. + +```go +result := facades.Process().Run("echo Hello, World!") +// /bin/sh -c ""echo Hello, World!"" on Linux/macOS +// cmd /c "echo Hello, World!" on Windows +``` + +The `Run` method returns a `Result` interface. The `Result` interface gives you convenient access to the output and status of the command: + +```go +result := facades.Process().Run("ls", "-la") + +result.Command() // string: The original command +result.Error() // error: The error returned by the command execution +result.ErrorOutput() // string: Output from Stderr +result.ExitCode() // int: The exit code (e.g., 0, 1) +result.Failed() // bool: True if the exit code was not 0 +result.Output() // string: Output from Stdout +``` + +### Process Options + +You often need to customize how a command runs, such as where it runs or what environment variables it sees. The `Process` facade provides a fluent API for this. + +#### Path + +You can use the `Path` method to specify the working directory for the command. If you don't set this, the process will execute in the current working directory of your application. + +```go +result := facades.Process().Path("/var/www/html").Run("ls", "-la") +``` + +#### Timeout + +To prevent a process from hanging indefinitely, you can enforce a timeout. If the process runs longer than the specified duration, it will be killed. + +```go +import "time" + +result := facades.Process().Timeout(10 * time.Minute).Run("sleep", "20") +``` + +#### Environment Variables + +You can pass custom environment variables to the process using the `Env` method. The process will also inherit the system's environment variables. + +```go +// Passes FOO=BAR along with existing system envs +result := facades.Process().Env(map[string]string{ + "FOO": "BAR", + "API_KEY": "secret", +}).Run("printenv") +``` + +#### Input (Stdin) + +If your command expects input from standard input (stdin), you can provide it using the `Input` method. This accepts an `io.Reader`. + +```go +import "strings" + +// Pipes "Hello Goravel" into the cat command +result := facades.Process(). + Input(strings.NewReader("Hello Goravel")). + Run("cat") +``` + +### Process Output + +You can access the process output after execution using the `Output` (standard output) and `ErrorOutput` (standard error) methods on the result object. + +```go +result := facades.Process().Run("ls", "-la") + +fmt.Println(result.Output()) +fmt.Println(result.ErrorOutput()) +``` + +If you need to process the output in real-time (streaming), you may register a callback using the `OnOutput` method. The callback receives two arguments: the output type (stdout or stderr) and the byte slice containing the output data. + +```go +import ( + "fmt" + "github.com/goravel/framework/contracts/process" +) + +result := facades.Process().OnOutput(func(typ process.OutputType, b []byte) { + // Handle real-time streaming here + fmt.Print(string(b)) +}).Run("ls", "-la") +``` + +If you only need to verify that the output contains a specific string after execution, you can use the `SeeInOutput` or `SeeInErrorOutput` helper methods. + +```go +result := facades.Process().Run("ls", "-la") + +if result.SeeInOutput("go.mod") { + // The file exists +} +``` + +#### Disabling Process Output + +If your process writes a large amount of data, you may want to control how it is stored. + +Using `Quietly` will prevent the output from bubbling up to the console or logs during execution, but the data will still be collected and available via `result.Output()`. + +If you do not need to access the final output at all and want to save memory, you can use `DisableBuffering`. This prevents the output from being stored in the result object, though you can still inspect the stream in real-time using `OnOutput`. + +```go +// Captures output but doesn't print it during execution +facades.Process().Quietly().Run("...") + +// Does not capture output (saves memory), but allows streaming +facades.Process().DisableBuffering().OnOutput(func(typ process.OutputType, b []byte) { + // ... +}).Run("...") +``` + +### Pipelines + +Sometimes you need to pipe the output of one process into the input of another. The `Process` facade makes this easy +using the `Pipe` method, which allows you to chain multiple commands together synchronously. + +```go +import "github.com/goravel/framework/contracts/process" + +result := facades.Process().Pipe(func(pipe process.Pipe) { + pipe.Command("echo", "Hello, World!") + pipe.Command("grep World") // string command: /bin/sh -c "grep World" + pipe.Command("tr", "a-z", "A-Z") +}).Run() +``` + +:::warning +Process options such as `Timeout`, `Env`, or `Input` must be configured **after** the `Pipe` method is called. +Any configuration applied before the `Pipe` call will be ignored. + +```go +// Correct: Configuration applied after Pipe +facades.Process().Pipe(...).Timeout(10 * time.Second).Run() + +// Incorrect: Timeout will be ignored +facades.Process().Timeout(10 * time.Second).Pipe(...).Run() +``` + +::: + +#### Pipeline Output & Keys + +You can inspect the output of the pipeline in real-time using the `OnOutput` method. When used with a pipe, +the callback signature changes to include a `key` (string), allowing you to identify which command produced the output. + +By default, the `key` is the numeric index of the command. However, you can assign a readable label to each command +using the `As` method, which is highly useful for debugging complex pipelines. + +```go +facades.Process().Pipe(func(pipe process.Pipe) { + pipe.Command("cat", "access.log").As("source") + pipe.Command("grep", "error").As("filter") +}).OnOutput(func(typ process.OutputType, line []byte, key string) { + // 'key' will be "source" or "filter" +}).Run() +``` + +## Asynchronous Processes + +While the `Run` method waits for the process to complete, `Start` can be used to invoke a process asynchronously. +This allows the process to run in the background while your application continues executing other tasks. The `Start` method returns a `Running` interface. + +```go +import "time" + +running, err := facades.Process().Timeout(10 * time.Second).Start("sleep", "5") + +// Continue doing other work... + +result := running.Wait() +``` + +To check if a process has finished without blocking, you may use the `Done` method. This returns a standard Go channel +that closes when the process exits, making it ideal for use in `select` statements. + +```go +running, err := facades.Process().Start("sleep", "5") + +select { +case <-running.Done(): + // Process finished successfully +case <-time.After(1 * time.Second): + // Custom logic if it takes too long +} + +result := running.Wait() +``` + +:::warning +Even if you use the `Done` channel to detect completion, you **must** call `Wait()` afterwards. +This ensures the process is properly "reaped" by the operating system and cleans up underlying resources. +::: + +### Process IDs & Signals + +You can retrieve the operating system's process ID (PID) for a running process using the `PID` method. + +```go +running, err := facades.Process().Start("ls", "-la") + +println(running.PID()) +``` + +#### Sending Signals + +Goravel provides methods to interact with the process lifecycle. You can send a specific OS signal using +the `Signal` method, or use the `Stop` helper to attempt a graceful shutdown. + +The `Stop` method is particularly useful: it will first send a termination signal (defaulting to `SIGTERM`). +If the process does not exit within the provided timeout, it will be forcibly killed (`SIGKILL`). + +```go +import ( + "os" + "time" +) + +running, err := facades.Process().Start("sleep", "60") + +// Manually send a signal +running.Signal(os.Interrupt) + +// Attempt to stop gracefully, wait 5 seconds, then force kill +running.Stop(5 * time.Second) +``` + +### Checking Process State + +You can inspect the current state of the process using the `Running` method. This is primarily useful for debugging +or health checks, as it provides a snapshot of whether the process is currently active. + +```go +// Snapshot check (useful for logs or metrics) +if running.Running() { + fmt.Println("Process is still active...") +} +``` + +:::tip +If you need to execute code **when** the process finishes, do not poll `Running()`. Instead, use the `Done()` channel +or the `Wait()` method, which are much more efficient than repeatedly checking the status. +::: + +## Concurrent Processes + +Goravel makes it easy to manage a pool of concurrent processes, allowing you to execute multiple commands simultaneously. +This is particularly useful for batch processing or running independent tasks in parallel. + +### Executing Pools + +To run a pool of processes, you may use the `Pool` method. This accepts a closure where you define the commands you wish to execute. + +By default, the `Pool` method waits for all processes to complete and returns a map of results keyed by the process name (or index). + +```go +results, err := facades.Process().Pool(func(pool process.Pool) { + pool.Command("sleep", "1").As("first") + pool.Command("sleep 2").As("second") // string command: /bin/sh -c "sleep 2" +}).Run() + +if err != nil { + panic(err) +} + +// Access results by their assigned key +println(results["first"].Output()) +println(results["second"].Output()) +``` + +### Naming Processes + +By default, processes in a pool are keyed by their numeric index (e.g., "0", "1"). However, for clarity and easier access +to results, you should assign a unique name to each process using the `As` method: + +```go +pool.Command("cat", "system.log").As("system") +``` + +### Pool Options + +The `Pool` builder provides several methods to control the execution behavior of the entire batch. + +#### Concurrency + +You can control the maximum number of processes running simultaneously using the `Concurrency` method. + +```go +facades.Process().Pool(func(pool process.Pool) { + // Define 10 commands... +}).Concurrency(2).Run() +``` + +#### Total Timeout + +You can enforce a global timeout for the entire pool execution using the `Timeout` method. If the pool takes longer +than this duration, all running processes will be terminated. + +```go +facades.Process().Pool(...).Timeout(1 * time.Minute).Run() +``` + +### Asynchronous Pools + +If you need to run the pool in the background while your application performs other tasks, you can use the `Start` +method instead of `Run`. This returns a `RunningPool` handle. + +```go +runningPool, err := facades.Process().Pool(func(pool process.Pool) { + pool.Command("sleep", "5").As("long_task") +}).Start() + +// Check if the pool is still running +if runningPool.Running() { + fmt.Println("Pool is active...") +} + +// Wait for all processes to finish and gather results +results := runningPool.Wait() +``` + +#### Interacting with Running Pools + +The `RunningPool` interface provides several methods to manage the active pool: + +- **`PIDs()`**: Returns a map of Process IDs keyed by the command name. +- **`Signal(os.Signal)`**: Sends a signal to all running processes in the pool. +- **`Stop(timeout, signal)`**: Gracefully stops all processes. +- **`Done()`**: Returns a channel that closes when the pool finishes, useful for `select` statements. + +```go +select { +case <-runningPool.Done(): + // All processes finished +case <-time.After(10 * time.Second): + // Force stop all processes if they take too long + runningPool.Stop(1 * time.Second) +} +``` + +### Pool Output + +You can inspect the output of the pool in real-time using the `OnOutput` method. + +:::warning +The `OnOutput` callback may be invoked concurrently from multiple goroutines. Ensure your callback logic is thread-safe. +::: + +```go +facades.Process().Pool(func(pool process.Pool) { + pool.Command("ping", "google.com").As("ping") +}).OnOutput(func(typ process.OutputType, line []byte, key string) { + // key will be "ping" + fmt.Printf("[%s] %s", key, string(line)) +}).Run() +``` + +### Per-Process Configuration + +Inside the pool definition, each command supports individual configuration methods similar to single processes: + +- **`Path(string)`**: Sets the working directory. +- **`Env(map[string]string)`**: Sets environment variables. +- **`Input(io.Reader)`**: Sets standard input. +- **`Timeout(time.Duration)`**: Sets a timeout for the specific command. +- **`Quietly()`**: Disables output capturing for this specific command. +- **`DisableBuffering()`**: Disables memory buffering (useful for high-volume output). + +```go +facades.Process().Pool(func(pool process.Pool) { + pool.Command("find", "/", "-name", "*.log"). + As("search"). + Path("/var/www"). + Timeout(10 * time.Second). + DisableBuffering() +}).Run() +``` From 201929071db3df3ebd9a0696d2d18f24dd636647 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:15 +0800 Subject: [PATCH 072/163] New translations compare-with-laravel.md (Uzbek) [skip ci] Update translations (Uzbek) compare-with-laravel.md --- uz_UZ/prologue/compare-with-laravel.md | 40 ++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 uz_UZ/prologue/compare-with-laravel.md diff --git a/uz_UZ/prologue/compare-with-laravel.md b/uz_UZ/prologue/compare-with-laravel.md new file mode 100644 index 000000000..ee7698b29 --- /dev/null +++ b/uz_UZ/prologue/compare-with-laravel.md @@ -0,0 +1,40 @@ +# Compare With Laravel + +Goravel is heavily inspired by the Laravel framework, aiming to bring similar elegance and simplicity to Go developers. Here are some key comparisons between Goravel and Laravel to help you understand how Goravel aligns with Laravel's features: + +| Feature | Goravel | Laravel | Code Example | +| -------------------------------------------------------------------------------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Artisan Console](https://www.goravel.dev/digging-deeper/artisan-console.html) | ✅ | ✅ | ./artisan key:generate
php artisan key:generate | +| [Authentication](https://www.goravel.dev/security/authentication.html) | ✅ | ✅ | facades.Auth(ctx).Login(&user)
Auth::login($user) | +| [Authorization](https://www.goravel.dev/security/authorization.html) | ✅ | ✅ | facades.Gate().Allows("update", user)
Gate::allows('update', $user) | +| [Cache](https://www.goravel.dev/digging-deeper/cache.html) | ✅ | ✅ | facades.Cache().Put("key", "value", time.Minute)
Cache::put('key', 'value', 60) | +| [Carbon](https://www.goravel.dev/digging-deeper/helpers.html) | ✅ | ✅ | carbon.Now().AddDays(1)
Carbon::now()->addDays(1) | +| [Config](https://www.goravel.dev/getting-started/configuration.html) | ✅ | ✅ | facades.Config().GetString("app.name")
config('app.name') | +| [Crypt](https://www.goravel.dev/security/encryption.html) | ✅ | ✅ | facades.Crypt().EncryptString("text")
Crypt::encryptString('text') | +| [DB](https://www.goravel.dev/database/getting-started.html) | ✅ | ✅ | facades.DB().Table("users").Get(&users)
DB::table('users')->get() | +| [Event](https://www.goravel.dev/digging-deeper/event.html) | ✅ | ✅ | facades.Event().Job(&events.Order{}).Dispatch()
Order::dispatch() | +| [Factory](https://www.goravel.dev/orm/factories.html) | ✅ | ✅ | facades.Orm().Factory().Make(&user)
User::factory()->make() | +| [FileStorage](https://www.goravel.dev/digging-deeper/filesystem.html) | ✅ | ✅ | facades.Storage().Put("file.txt", "content")
Storage::put('file.txt', 'content') | +| [Hash](https://www.goravel.dev/security/hashing.html) | ✅ | ✅ | facades.Hash().Make("password")
Hash::make('password') | +| [Http](https://www.goravel.dev/the-basics/routing.html) | ✅ | ✅ | facades.Route().Get("/", controller.Index)
Route::get('/', [Controller::class, 'index']) | +| [Http Client](https://www.goravel.dev/digging-deeper/http-client.html) | ✅ | ✅ | facades.Http().Get("https://api.com")
Http::get('https://api.com') | +| [Localization](https://www.goravel.dev/digging-deeper/localization.html) | ✅ | ✅ | facades.Lang(ctx).Get("messages.welcome")
__('messages.welcome') | +| [Logger](https://www.goravel.dev/the-basics/logging.html) | ✅ | ✅ | facades.Log().Info("message")
Log::info('message') | +| [Mail](https://www.goravel.dev/digging-deeper/mail.html) | ✅ | ✅ | facades.Mail().To("user@example.com").Send()
Mail::to('user@example.com')->send(new Order()) | +| [Mock](https://www.goravel.dev/testing/mock.html) | ✅ | ✅ | | +| [Migrate](https://www.goravel.dev/database/migrations.html) | ✅ | ✅ | ./artisan migrate
php artisan migrate | +| [Orm](https://www.goravel.dev/orm/getting-started.html) | ✅ | ✅ | facades.Orm().Query().Find(&user, 1)
User::find(1) | +| [Package Development](https://www.goravel.dev/digging-deeper/package-development.html) | ✅ | ✅ | | +| [Process](https://www.goravel.dev/digging-deeper/process.html) | ✅ | ✅ | facades.Process().Run("ls", "-la")
\`Process::run('ls -la') | +| [Queue](https://www.goravel.dev/digging-deeper/queues.html) | ✅ | ✅ | facades.Queue().Job(&jobs.Process{}).Dispatch()
Process::dispatch() | +| [Rate Limiting](https://www.goravel.dev/digging-deeper/process.html) | ✅ | ✅ | facades.RateLimiter().For("global", ...)
RateLimiter::for('global', ...) | +| [Seeder](https://www.goravel.dev/database/seeding.html) | ✅ | ✅ | facades.Seeder().Call([]seeder.Seeder{&User{}})
$this->call([User::class]) | +| [Session](https://www.goravel.dev/the-basics/session.html) | ✅ | ✅ | ctx.Request().Session().Put("key", "value")
session(['key' => 'value']) | +| [Task Scheduling](https://www.goravel.dev/digging-deeper/task-scheduling.html) | ✅ | ✅ | facades.Schedule().Command("emails:send").Daily()
Schedule::command('emails:send')->daily() | +| [Testing](https://www.goravel.dev/testing/getting-started.html) | ✅ | ✅ | | +| [Validation](https://www.goravel.dev/the-basics/validation.html) | ✅ | ✅ | ctx.Request().ValidateRequest()
$request->validate() | +| [View](https://www.goravel.dev/the-basics/views.html) | ✅ | ✅ | ctx.Response().View().Make("welcome.tmpl")
view('welcome') | +| [Grpc](https://www.goravel.dev/the-basics/grpc.html) | ✅ | 🚧 | | +| Notifications | 🚧 | ✅ | | +| Broadcasting | 🚧 | ✅ | | +| Livewire | 🚧 | ✅ | | From 2689369a7c3872e248a27e966bc98280a5d5af52 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 16:13:17 +0800 Subject: [PATCH 073/163] New translations v1.17.md (Uzbek) [skip ci] Update translations (Uzbek) v1.17.md --- uz_UZ/upgrade/v1.17.md | 570 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 570 insertions(+) create mode 100644 uz_UZ/upgrade/v1.17.md diff --git a/uz_UZ/upgrade/v1.17.md b/uz_UZ/upgrade/v1.17.md new file mode 100644 index 000000000..2a628adf6 --- /dev/null +++ b/uz_UZ/upgrade/v1.17.md @@ -0,0 +1,570 @@ +# Upgrading To v1.17 From v1.16 + +## Exciting New Features 🎉 + +- [Goravel Lite](#goravel-lite) +- [Simplified Code Structure](#simplified-code-structure) +- [Process Facade](#process-facade) +- [Pluralizer Package](#pluralizer-package) +- [Service Provider Runners](#service-provider-runners) + +## Enhancements 🚀 + +- [facades can be installed and uninstalled as needed](#facades-can-be-installed-and-uninstalled-as-needed) +- [Mail can be sent via template](#mail-can-be-sent-via-template) +- [The build command supports more flags](#the-build-command-supports-more-flags) +- [Add and modify functions for DB and Orm](#add-and-modify-functions-for-db-and-orm) +- [Add new functions for Schema](#add-new-functions-for-schema) +- [Add new commands](#add-new-commands) +- [Add CSRF token middleware](#add-csrf-token-middleware) +- [Command supports configure Arguments](#command-supports-configure-arguments) +- [make:migration supports create migration via model](#make-migration-supports-create-migration-via-model) +- [Optimize gRPC client connections](#optimize-grpc-connections) +- [Log supports print json format](#log-supports-print-json-format) +- [Http supports multiple clients](#http-supports-multiple-clients) +- [Validation supports pass context](#validation-supports-pass-context) +- [Add WithoutGlobalScopes function for Orm](#add-withoutglobalscopes-function-for-orm) + +## Breaking Changes 🛠 + +- [Remove machinery queue driver](#remove-machinery-queue-driver) +- [Modify gRPC configuration](#modify-grpc-configuration) +- [Switch log driver](#switch-log-driver) +- [Optimize migrate:rollback command](#optimize-migrate-rollback-command) +- [Remove Http.Request.Bind function](#remove-http-request-bind-function) +- [Modify package setup method](#modify-package-setup-method) + +## v1.17.1 + +- [Fix the build command with static flag failure](#fix-the-build-command-with-static-flag-failure) +- [Fix some make commands do not adapt the old code structure](#fix-some-make-commands-do-not-adapt-the-old-code-structure) +- [Optimize setup when installing package in old version project](#optimize-setup-when-installing-package-in-old-version-project) +- [Fix delay task issue when queue concurrency is greater than 1](#fix-delay-task-issue-when-queue-concurrency-is-greater-than-1) + +## v1.17.2 + +- [Fix the migrate:rollback command](#fix-the-migrate-rollback-command) + +## Upgrade Guide + +As [Golang v1.23 is no longer maintained](https://endoflife.date/go), the Golang version of Goravel supports has been upgraded from 1.23 to 1.24. + +goravel/example project from v1.16 to v1.17 PR can be used as an upgrade reference: [goravel/example#93](https://github.com/goravel/example/pull/93). + +### 1. Update dependencies + +```shell +go get github.com/goravel/framework@latest + +// If using gin +go get github.com/goravel/gin@latest + +// If using fiber +go get github.com/goravel/fiber@latest + +// If using redis +go get github.com/goravel/redis@latest + +// If using S3 +go get github.com/goravel/s3@latest + +// If using Oss +go get github.com/goravel/oss@latest + +// If using Cos +go get github.com/goravel/cos@latest + +// If using Minio +go get github.com/goravel/minio@latest + +go mod tidy + +// If using installer +goravel upgrade +``` + +### 2. Add new service providers + +```go +// config/app.go +import ( + ... + "github.com/goravel/framework/process" + "github.com/goravel/framework/view" +) + +"providers": []foundation.ServiceProvider{ + ... + &process.ServiceProvider{}, // [!code ++] + &view.ServiceProvider{}, // [!code ++] +}, +``` + +### 3. Modify http client configuration + +Add new configuration in `config/http.go`: + +```go +"client": map[string]any{ // [!code --] + "base_url": config.GetString("HTTP_CLIENT_BASE_URL"), // [!code --] + "timeout": config.GetDuration("HTTP_CLIENT_TIMEOUT"), // [!code --] + "max_idle_conns": config.GetInt("HTTP_CLIENT_MAX_IDLE_CONNS"), // [!code --] + "max_idle_conns_per_host": config.GetInt("HTTP_CLIENT_MAX_IDLE_CONNS_PER_HOST"), // [!code --] + "max_conns_per_host": config.GetInt("HTTP_CLIENT_MAX_CONN_PER_HOST"), // [!code --] + "idle_conn_timeout": config.GetDuration("HTTP_CLIENT_IDLE_CONN_TIMEOUT"), // [!code --] +}, // [!code --] +"default_client": config.Env("HTTP_CLIENT_DEFAULT", "default"), // [!code ++] +"clients": map[string]any{ // [!code ++] + "default": map[string]any{ // [!code ++] + "base_url": config.Env("HTTP_CLIENT_BASE_URL", ""), // [!code ++] + "timeout": config.Env("HTTP_CLIENT_TIMEOUT", "30s"), // [!code ++] + "max_idle_conns": config.Env("HTTP_CLIENT_MAX_IDLE_CONNS", 100), // [!code ++] + "max_idle_conns_per_host": config.Env("HTTP_CLIENT_MAX_IDLE_CONNS_PER_HOST", 2), // [!code ++] + "max_conns_per_host": config.Env("HTTP_CLIENT_MAX_CONN_PER_HOST", 0), // [!code ++] + "idle_conn_timeout": config.Env("HTTP_CLIENT_IDLE_CONN_TIMEOUT", "90s"), // [!code ++] + }, // [!code ++] +}, // [!code ++] +``` + +### 4. Modify gRPC configuration + +Need to modify accordingly: [Modify gRPC configuration](#modify-grpc-configuration) + +### 5. If you want to send mail via template + +Add new configuration in `config/mail.go`: + +```go +// Template Configuration +// +// This controls template rendering for email views. Template engines are cached +// globally and support both built-in drivers and custom implementations via factories. +// +// Available Drivers: "html", "custom" +"template": map[string]any{ + "default": config.Env("MAIL_TEMPLATE_ENGINE", "html"), + "engines": map[string]any{ + "html": map[string]any{ + "driver": "html", + "path": config.Env("MAIL_VIEWS_PATH", "resources/views/mail"), + }, + }, +}, +``` + +### 6. If you developed a custom package and install it via `package:install` command + +Need to modify accordingly: [Modify package setup method](#modify-package-setup-method) + +### 7. If you are using machinery queue driver + +Need to modify accordingly: [Remove machinery queue driver](#remove-machinery-queue-driver) + +### 8. If you created a custom log driver + +Need to modify accordingly: [Switch log driver](#switch-log-driver) + +### 9. If you are using Http.Request.Bind function + +Need to modify accordingly: [Remove Http.Request.Bind function](#remove-http-request-bind-function) + +### 10. If you are using validation.Make function or custom rules/filters + +Need to modify accordingly: [Validation supports pass context](#validation-supports-pass-context) + +### 11. If you are using global scopes in Orm + +Need to modify accordingly: [Add WithoutGlobalScopes function for Orm](#add-withoutglobalscopes-function-for-orm) + +## Feature Introduction + +### Goravel Lite + +We are excited to introduce [Goravel Lite](https://github.com/goravel/goravel-lite), a lightweight version of the Goravel framework, designed for developers who want to build applications with minimal dependencies and a smaller footprint. It provides the core features of Goravel while allowing developers to add only the components they need. + +- Only includes essential facades: `Artisan`, `Config`, reducing bloat and improving performance. +- Other facades can be installed and uninstalled as needed via the `package:install` and `package:uninstall` commands. +- `goravel/goravel` == `goravel/goravel-lite` + all facades. Any improvements for `goravel/goravel` should be submitted to `goravel/goravel-lite`, then a specify github action will sync the changes to `goravel/goravel`. And `goravel/goravel` is still the main repository for users to use Goravel framework. + +### Simplified code structure + +The code structure has been simplified to improve maintainability and readability to consitent with Laravel. The old structure can still be used, it's a backward compatible change. It's a bit complicated to migrate from old structure to new structure, there is an example PR for reference if needed: [goravel/example#91](https://github.com/goravel/example/pull/91). + +1. Remove all `kenel.go` and default `*_service_providers.go` files. Move configurations in `*_service_providers.go` files to the `bootstrap` folder. +2. Move all facades from framework intenal to the `app/facades` folder, users can customize or extend them as needed. +3. Simplify the facades startup process, no need to run facades in `main.go` anymorem, please refer to [Service Provider Runners](../architecture-concepts/service-providers.md#runners) for more details. +4. Support customize directory structure via the `WithPath()` function, please refer to [Customize Directory Structure](../getting-started/directory-structure.md#customize-directory-structure) for more details. + +### Process Facade + +Goravel now provides an expressive and elegant API around Go's standard `os/exec` package, allowing you to invoke external commands from your application seamlessly. + +[View Document](../digging-deeper/processes.md) + +### Pluralizer package + +Goravel now includes a pluralizer package that helps with converting words between singular and plural forms based on language rules. This is useful for applications that need to handle different languages and their grammatical rules. + +[View Document](../digging-deeper/pluralization.md) + +### Service Provider Runners + +Service Providers can now implement the `Runners` interface to run code when the application starts. This is typically used to start or shutdown services defined in the Service Provider, such as Route, Schedule, Queue, etc. You no longer need to start or shutdown these services manually in `main.go`, as Goravel will handle it for you. + +This feature is only available when using [the new simplified code structure](#simplified-code-structure). + +[View Document](../architecture-concepts/service-providers.md#runners) + +### Log supports print json format + +Goravel's logging system now supports outputting logs in JSON format, making it easier to integrate with log management systems and perform structured logging. + +```go +"channels": map[string]any{ + "daily": map[string]any{ + "driver": "daily", + "path": "storage/logs/goravel.log", + "level": config.Env("LOG_LEVEL", "debug"), + "days": 7, + "print": true, + // the value can be "text" or "json" + "formatter": "json", // [!code ++] + }, +}, +``` + +### Http supports multiple clients + +Goravel's HTTP client module now supports multiple clients, allowing you to define and use different HTTP clients with their own configurations for various purposes within your application. + +[View Document](../digging-deeper/http-client.md#making-requests) + +### Validation supports pass context + +Goravel's validation module now supports passing context to validation functions, enabling more flexible and dynamic validation scenarios based on the context of the request or operation. + +```go +validator, err := facades.Validation().Make(input, rules) // [!code --] +validator, err := facades.Validation().Make(ctx, input, rules) // [!code ++] +``` + +Custom rules and filters also support context parameter: + +```go +type Rule interface { + Signature() string + Passes(data Data, val any, options ...any) bool // [!code --] + Message() string // [!code --] + Passes(ctx context.Context, data Data, val any, options ...any) bool // [!code ++] + Message(ctx context.Context) string // [!code ++] +} + +type Filter interface { + Signature() string + Handle() any // [!code --] + Handle(ctx context.Context) any // [!code ++] +} +``` + +### Add WithoutGlobalScopes function for Orm + +A new `WithoutGlobalScopes` function has been added to the Orm package, allowing you to exclude all global scopes from a query. This is useful when you want to retrieve records without the constraints imposed by global scopes. + +```go +var user []User +err := facades.Orm().Model(&User{}).WithoutGlobalScopes().Get(&user) +err := facades.Orm().Model(&User{}).WithoutGlobalScopes("name").Get(&user) +``` + +In order to support set global scope name, the `GlobalScope` interface of model has been modified: + +```go +import "github.com/goravel/framework/contracts/orm" + +type User struct { + orm.Model + Name string +} + +func (r *User) GlobalScopes() []func(orm.Query) orm.Query { // [!code --] +func (r *User) GlobalScopes() map[string]func(orm.Query) orm.Query { // [!code ++] + return map[string]func(orm.Query) orm.Query{ + "name": func(query orm.Query) orm.Query { + return query.Where("name", "goravel") + }, + } +} +``` + +### facades can be installed and uninstalled as needed + +Follow the release of [Goravel Lite](#goravel-lite), now facades can be installed and uninstalled as needed via the `package:install` and `package:uninstall` commands. Notice: this feature is only available when you project is built with Goravel Lite or upgrades to [the new simplified code structure](#simplified-code-structure). + +[View Document](../architecture-concepts/facades.md#install-uninstall-facades) + +### Mail can be sent via template + +Mail sending now supports templates, allowing you to send emails using predefined templates for better consistency and easier management. The template supports http/template and custom drivers. + +[View Document](../digging-deeper/mail.md#using-template) + +### The build command supports more flags + +Add new `--arch` and `--static` flags to the `build` command, allowing you to specify the target architecture and whether to build a static binary. + +### Add and modify functions for DB and Orm + +New functions: + +- `Avg(column string, dest any) error`: Calculate the average value of a column. +- `Min(column string, dest any) error`: Find the minimum value of a column. +- `Max(column string, dest any) error`: Find the maximum value of a column. +- `WhereAll(columns []string, args ...any) Query`: Adds a "where all columns match" clause to the query. +- `WhereAny(columns []string, args ...any) Query`: Adds a "where any column matches" clause to the query. +- `WhereNone(columns []string, args ...any) Query`: Adds a "where none of the columns match" clause to the query. + +Modified functions: + +```go +// Before +Sum(column string) (int64, error) + +// After +Sum(column string, dest any) error +``` + +### Add new functions for Schema + +New functions have been added to the Schema package to enhance database schema management capabilities. + +- `DateTimes`: Create `created_at` and `updated_at` columns on the table. +- `ForeignID`: Create an unsigned big integer column for foreign keys. +- `ForeignUlid`: Create a ULID column for foreign keys. +- `ForeignUuid`: Create a UUID column for foreign keys. + +### Add new commands + +- `make:provider`: Create a new service provider class. +- `make:view`: Create a new view template file. + +### Add CSRF token middleware + +A new middleware has been added to protect against Cross-Site Request Forgery (CSRF) attacks. This middleware can be applied to routes to ensure that requests are coming from authenticated sources. + +[View Document](../the-basics/views.md#csrf-token-middleware) + +### Command supports configure Arguments + +Commands now support configuring arguments, allowing you to define and handle command-line arguments more effectively within your custom commands. + +[View Document](../digging-deeper/artisan-console.md#arguments) + +### make:migration supports create migration via model + +The `make:migration` command has been enhanced to support creating migrations based on existing models. This allows for quicker migration creation by leveraging the structure defined in your models. + +[View Document](../database/migrations.md#create-migrations) + +### Optimize gRPC client connections + +A client connection pool has been implemented for gRPC clients to optimize performance and resource utilization. This allows for reusing existing connections rather than creating new ones for each request, reducing latency and improving efficiency. + +### Remove machinery queue driver + +The machinery queue driver has been removed totally given it's deprecated in v1.16. Please follow the guidelines in the [v1.16 upgrade document](./v1.16.md#optimize-queue-module-configuration) to migrate to other queue drivers if you are still using it. + +### Modify gRPC configuration + +The grpc configuration `grpc.clients` has been modified to `grpc.servers`, and the `facades.Grpc().Client()` function has been deprecated and will be removed in v1.18, please use the `facades.Grpc().Connect()` function instead. + +```go +// config/grpc.go +"clients": map[string]any{ // [!code --] +"servers": map[string]any{ // [!code ++] +``` + +```go +facades.Grpc().Client(ctx, "name") // [!code --] +facades.Grpc().Connect("name") // [!code ++] +``` + +### Switch log driver + +The log driver has been switched from `logrus` to `log/slog` for better performance and structured logging capabilities. + +The custom log driver interface has been modified: + +```go +// framework/contracts/log/Logger +package log + +type Logger interface { + // Handle pass channel config path here + Handle(channel string) (Hook, error) // [!code --] + Handle(channel string) (Handler, error) // [!code ++] +} +``` + +You can use `log.HookToHandler` function to adapt old custom log drivers: + +```go +type CustomLogger struct {} + +func (logger *CustomLogger) Handle(channel string) (log.Handler, error) { + hook := /* your old custom log driver logic */ + + return log.HookToHandler(hook), nil +} +``` + +### Optimize migrate:rollback command + +Previously, the `migrate:rollback` command only rolls back one migration at a time, it's not consistent with Laravel's behavior. Now the command will roll back all migrations from the last batch by default. You can still use the `--step` option to specify the number of batches to roll back. + +### Remove Http.Request.Bind function + +The `Bind` function on the `Http.Request` interface has been removed. You can now use the `Bind` method via `response`. + +```go +var user User +response, err := facades.Http().Bind(&user).Get("https://github.com") // [!code --] +response, err := facades.Http().Get("https://github.com") // [!code ++] +err = response.Bind(&user) // [!code ++] +``` + +### Modify package setup method + +Previously, the package service provider can be installed to `config/app.go` via the `setup.go` file when running the `package:install` command. Now the service provider is supported to be installed to the `bootstrap/providers.go` file given [Simplified Code Structure](#simplified-code-structure) is launched. + +If you only want to support the new code structure: + +```go +// setup/setup.go +package main + +import ( + "os" + + "github.com/goravel/framework/packages" + "github.com/goravel/framework/packages/match" + "github.com/goravel/framework/packages/modify" + "github.com/goravel/framework/support/path" +) + +func main() { + // Initialize setup to get paths, this should be called at the beginning. + setup := packages.Setup(os.Args) // [!code ++] + + appConfigPath := path.Config("app.go") + postgresServiceProvider := "&postgres.ServiceProvider{}" + + // In the new code structures, the GetModulePath function is removed, use setup.Paths().Module().Import() instead + modulePath := packages.GetModulePath() // [!code --] + moduleImport := setup.Paths().Module().Import() // [!code ++] + + packages.Setup(os.Args).Install( // [!code --] + setup.Install( // [!code ++] + // Add postgres service provider + modify.GoFile(appConfigPath). // [!code --] + Find(match.Imports()).Modify(modify.AddImport(modulePath)). // [!code --] + Find(match.Providers()).Modify(modify.Register(postgresServiceProvider)), // [!code --] + modify.RegisterProvider(moduleImport, postgresServiceProvider), // [!code ++] + ... + ). + Uninstall( + // Remove postgres service provider + modify.GoFile(appConfigPath). // [!code --] + Find(match.Providers()).Modify(modify.Unregister(postgresServiceProvider)). // [!code --] + Find(match.Imports()).Modify(modify.RemoveImport(modulePath)), // [!code --] + modify.UnregisterProvider(moduleImport, postgresServiceProvider), // [!code ++] + ... + ). + Execute() +} +``` + +If you want to support both old and new code structures in your package, please use the following setup method. In summary, you need to check whether the project is using the new code structure via the `env.IsBootstrapSetup()` function, then apply different modifications accordingly. Notice: `match.Providers()` should be replaced with `match.ProvidersInConfig()` when adapting the old code structure. + +```go +package main + +import ( + "os" + + "github.com/goravel/framework/packages" + "github.com/goravel/framework/packages/match" + "github.com/goravel/framework/packages/modify" + "github.com/goravel/framework/support/env" + "github.com/goravel/framework/support/path" +) + +func main() { + // Initialize setup to get paths, this should be called at the beginning. + setup := packages.Setup(os.Args) + + appConfigPath := path.Config("app.go") + postgresServiceProvider := "&postgres.ServiceProvider{}" + + // Use the new setup.Paths().Module().Import() method to get the module import path + moduleImport := setup.Paths().Module().Import() + + setup.Install( + // Add postgres service provider to app.go if using the old code structure + modify.When(func(_ map[string]any) bool { + return !env.IsBootstrapSetup() + }, modify.GoFile(appConfigPath). + Find(match.Imports()).Modify(modify.AddImport(moduleImport)). + Find(match.ProvidersInConfig()).Modify(modify.Register(postgresServiceProvider))), + + // Add postgres service provider to providers.go if using the new code structure + modify.When(func(_ map[string]any) bool { + return env.IsBootstrapSetup() + }, modify.RegisterProvider(moduleImport, postgresServiceProvider)), + + ).Uninstall( + // Remove postgres service provider from app.go if using the old code structure + modify.When(func(_ map[string]any) bool { + return !env.IsBootstrapSetup() + }, modify.GoFile(appConfigPath). + Find(match.ProvidersInConfig()).Modify(modify.Unregister(postgresServiceProvider)). + Find(match.Imports()).Modify(modify.RemoveImport(moduleImport))), + + // Remove postgres service provider from providers.go if using the new code structure + modify.When(func(_ map[string]any) bool { + return env.IsBootstrapSetup() + }, modify.UnregisterProvider(moduleImport, postgresServiceProvider)), + ).Execute() +} +``` + +### Fix the build command with static flag failure + +goravel/framework: v1.17.1 + +The `./artisan build -s` command with the `--static` flag failed due to the Go version upgrade to 1.24. + +### Fix some make commands do not adapt the old code structure + +goravel/framework: v1.17.1 + +`make:rule`, `make:filter`, `make:migration`, `make:package`, etc. commands do not adapt the old code structure when generating files. Now these commands can detect whether the project is using the new simplified code structure via the `env.IsBootstrapSetup()` function, then generate files to the correct directories accordingly. + +### Optimize setup when installing package in old version project + +goravel/framework: v1.17.1 + +If you built a custom package, the `Providers` function in the `setup.go` file has been modified to adapt the new code structure. Hence, if you want to support the old code structure, it should be replaced with the `ProvidersInConfig` function. Please refer to [Modify package setup method](#modify-package-setup-method) for more details. + +### Fix delay task issue when queue concurrency is greater than 1 + +goravel/framework: v1.17.1 + +goravel/redis: v1.17.1 + +When the queue worker concurrency is greater than 1, delay tasks will be executed several times. This is because multiple workers may pick up the same delayed task when it becomes available. Now a distributed lock is used to ensure that only one worker can execute the delayed task at a time. + +### Fix the migrate:rollback command + +goravel/framework: v1.17.2 + +Previously, the `migrate:rollback` command set the batch number of rolled back migrations to 1 as default, which caused issues when rolling back. Now the command will set the batch number to the last batch number instead of 1. From e6f71067be5e62cec51fea8b70416f33d105b199 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 19:07:33 +0800 Subject: [PATCH 074/163] New translations facades.md (Uzbek) [skip ci] Update translations (Uzbek) facades.md --- uz_UZ/architecture-concepts/facades.md | 30 +++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/uz_UZ/architecture-concepts/facades.md b/uz_UZ/architecture-concepts/facades.md index 49f6569f5..9a5d99fa9 100644 --- a/uz_UZ/architecture-concepts/facades.md +++ b/uz_UZ/architecture-concepts/facades.md @@ -1,10 +1,10 @@ -# Facades +# Fasadlar [[toc]] -## Introduction +## Kirish -`facades` provide a "static" interface for the core functionality of the application and provide a more flexible, more elegant, and easy-to-test syntax. All `facades` of Goravel are defined under the `app/facades` folder: +`facades` ilova yadrosining asosiy funksiyalari uchun "static" interfeysni ta'minlaydi va ko'proq moslashuvchan, chiroyli va sinov o'tkazish oson bo'lgan sintaksisni taqdim etadi. Goravel’ning barcha facadelari app/facades papkasi ichida joylashgan: ```go import "app/facades" @@ -12,11 +12,11 @@ import "app/facades" facades.Config().GetString("app.host") ``` -## How Facades Work +## Fasadlar qanday ishlaydi -Each service provider registers its corresponding bindings in the service container, then the service container providers vairous `Make*` functions to build the binding instances. The `facades` in the `app/facades` folder call these `Make*` functions to get the instances from the service container. Let's use the `Route` facade as an example: +Har bir xizmat ko'rsatuvchi o'zining mos bog'lanishlarini xizmat konteynerida ro'yxatdan o'tkazadi, so'ngra xizmat konteyneri bog'lanish namunalarini yaratish uchun turli `Make*` funksiyalarini taqdim etadi. `app/facades` papkasidagi `facades`lar xizmat konteyneridan namunalarni olish uchun ushbu `Make*` funksiyalarini chaqiradi. Keling, `Route` fasadini misol sifatida ishlatamiz: -1. The `Route` service provider registers the `binding.Route` binding in the service container: +1. `Route` xizmat provayderi xizmat konteynerida `binding.Route` bog'lanishini ro'yxatdan o'tkazadi: ```go type ServiceProvider struct {} @@ -30,7 +30,7 @@ func (r *ServiceProvider) Register(app foundation.Application) { func (r *ServiceProvider) Boot(app foundation.Application) {} ``` -2. The `Route` facade calls the `MakeRoute()` function to get the `Route` instance from the service container: +2. `Route` fasadı `MakeRoute()` funksiyasini chaqirib, xizmat konteyneridan `Route` vorislarini olish uchun: ```go // app/facades/route.go @@ -45,24 +45,24 @@ func Route() route.Route { } ``` -> Given that the `facades` is exposed to the application, you can also create your own `facades` or override the existing `facades` in the `app/facades` folder. +> `facades` ilovaga ochiq bo'lganligi sababli, siz o'zingizning `facades`laringizni yaratishingiz yoki mavjud `facades`larni `app/facades` papkasida almashtirishingiz mumkin. -## Install/Uninstall Facades +## Fasadlarni o'rnatish/o'chirish -[goravel/goravel](https://github.com/goravel/goravel) installs all `facades` by default and [goravel/goravel-lite](https://github.com/goravel/goravel-lite) only installs essential `facades` like `Artisan`, `Config`. You can install or uninstall other `facades` as needed via the `package:install` and `package:uninstall` commands. +[goravel/goravel](https://github.com/goravel/goravel) standart boʻyicha barcha `facade`larni oʻrnatadi va [goravel/goravel-lite](https://github.com/goravel/goravel-lite) faqat `Artisan`, `Config` kabi muhim `facade`larni oʻrnatadi. Siz "package:install" va "package:uninstall" buyruqlari orqali boshqa `facades`larni kerak bo‘lganda o‘rnatishingiz yoki o‘chirishingiz mumkin. ```shell -# Install a specific facade +# Muayyan fasadni o'rnatish ./artisan package:install Route -# Install all facades +# Barcha fasadlarni o'rnatish ./artisan package:install --all -# Install all facades with default drivers +# Standart drayverlar bilan barcha fasadlarni o'rnatish ./artisan package:install --all --default -# Uninstall a specific facade +# Muayyan fasadni o'chirish ./artisan package:uninstall Route ``` -> Notice: if you are using the `./artisan package:install` command to choose the `facades` manually, you need to press `x` to select the facades you want to install, then press `Enter` to confirm. `facades` to'g'ridan-to'g'ri `Enter` tugmasini bosganingizda tanlanmaydi. +> Eslatma: agar siz `./artisan package:install` buyrug'i orqali `facades`ni qo'lda tanlashni istasangiz, o'rnatmoqchi bo'lgan fasadlarni tanlash uchun `x` tugmasini bosing, so'ngra tasdiqlash uchun `Enter` tugmasini bosing. `facades` to'g'ridan-to'g'ri `Enter` tugmasini bosganingizda tanlanmaydi. From 66dcb6b385c7f4d107bbefe933eeedefe6ff4eb2 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 19:07:34 +0800 Subject: [PATCH 075/163] New translations request-lifecycle.md (Uzbek) [skip ci] Update translations (Uzbek) request-lifecycle.md --- .../architecture-concepts/request-lifecycle.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/uz_UZ/architecture-concepts/request-lifecycle.md b/uz_UZ/architecture-concepts/request-lifecycle.md index 5f3b90be5..bdf9b3263 100644 --- a/uz_UZ/architecture-concepts/request-lifecycle.md +++ b/uz_UZ/architecture-concepts/request-lifecycle.md @@ -1,27 +1,27 @@ -# Request Lifecycle +# So‘rovning ishlash jarayoni [[toc]] -## Introduction +## Kirish -Using any tool in the real world feels more intuitive when you know how it works. This document aims to give you a clear, high-level look at how Goravel functions. Don’t worry if you don’t get every term right away—just aim for a basic sense of how things work, and your expertise will grow as you explore the rest of the docs. +Har qanday vositadan real hayotda foydalanish, uning qanday ishlashini bilganingizda yanada intuitiv va tushunarli bo‘ladi. Ushbu hujjat sizga Goravel qanday ishlashini aniq va umumiy darajada tushuntirib berishni maqsad qiladi. Agar har bir atamani darhol to'g'ri tushunmasangiz, tashvishlanmang - faqat narsalar qanday ishlashini asosiy ma'noda tushunishga harakat qiling, va siz qo'llanmaning qolgan qismini o'rganayotganda bilimingiz o'sib boradi. -## Lifecycle Overview +## Ishlash jarayonining umumiy tavsifi -1. The `main.go` is the entry point of the application, it will call the `bootstrap.Boot()` function to initialize the framework, and use `app.Wait()` to keep the application running. +1. `main.go` ilova kirish nuqtasi hisoblanadi, u `bootstrap.Boot()` funksiyasini chaqirib freymvorkni ishga tushiradi va `app.Wait()` yordamida ilovani ishlashda saqlaydi. -2. The `bootstrap.Boot()` function will initialize a new Goravel application instance by calling `foundation.Setup()`, you can set service providers, routes, and other settings like migrations, schedules via `With*` functions here. Finally, call the `Create()` method to boot the application. +2. `bootstrap.Boot()` funksiyasi `foundation.Setup()`ni chaqirib, yangi Goravel ilova namunasini ishga tushiradi, siz bu yerda `With*` funksiyalari orqali xizmat provayderlari, marshrutlar va migratsiyalar, jadvallar kabi boshqa sozlamalarni o‘rnatishingiz mumkin. Oxirida, ilovani ishga tushirish uchun Create() metodini chaqiring. -3. In the `Create()` method, it will first load configuration, then register all service providers and other settings. Finally, boot all service providers, return the application instance. +3. `Create()` usulida, avval konfiguratsiya yuklanadi, so'ngra barcha xizmat provayderlari va boshqa sozlamalar ro'yxatdan o'tkaziladi. Oxirida, barcha service providerlarni ishga tushirib, ilova vorisini qaytaring. -4. After the application is created, you can normally use all facades in this stage, but remember that your customize code should be placed before `app.Start()` in the `main.go` file. Or you can add your code into the `WithCallback` function in the `bootstrap/app.go` file to make sure your code is executed after the application is created. When running `app.Start()`, the http or grpc server will be started automatically if you have configured them. +4. Ilova yaratilgandan so'ng, siz ushbu bosqichda barcha fasadlarni odatdagidek ishlatishingiz mumkin, lekin esda tutingki, sizning moslashtirilgan kodingiz `main.go` faylida `app.Start()` dan oldin joylashtirilishi kerak. Yoki ilova yaratilgandan keyin kodingiz bajarilishini ta'minlash uchun `bootstrap/app.go` faylidagi `WithCallback` funksiyasiga kodingizni qo'shishingiz mumkin. app.Start() ishga tushirilganda, agar siz ularni sozlagan bo‘lsangiz, HTTP yoki gRPC server avtomatik tarzda ishga tushadi. ```go func Boot() contractsfoundation.Application { return foundation.Setup(). WithConfig(config.Boot). WithCallback(func() { - // Your custom code here, all facades are available here. + // Bu yerda sizning maxsus kodingiz, barcha fasadlar bu yerda mavjud. }). Create() } From 3794d3ea289f6afd34aab22ca8f7b39189d8a81d Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 28 Mar 2026 19:07:35 +0800 Subject: [PATCH 076/163] New translations en.ts (Uzbek) [skip ci] Update translations (Uzbek) en.ts --- .vitepress/config/uz_UZ.ts | 60 +++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/.vitepress/config/uz_UZ.ts b/.vitepress/config/uz_UZ.ts index 4dafc2d60..7e314c06a 100644 --- a/.vitepress/config/uz_UZ.ts +++ b/.vitepress/config/uz_UZ.ts @@ -1,39 +1,39 @@ import { defineConfig, type DefaultTheme } from 'vitepress'; export const config = defineConfig({ lang: 'en-US', - description: 'Goravel is a web application framework with complete functions and excellent scalability. As a starting scaffolding to help Gopher quickly build their own applications.', + description: "Goravel — bu to‘liq funksiyalarga ega va yuqori darajada kengaytiriladigan web-ilovalar frameworki hisoblanadi. U Go dasturchilari (gopherlar) uchun boshlang‘ich platforma (scaffolding) sifatida xizmat qiladi va ularga o‘z ilovalarini tez, tartibli va professional tarzda yaratishga yordam beradi.", themeConfig: { nav: nav(), sidebar: [{ - text: 'Prologue', + text: "Kirish", base: '/prologue/', items: sidebarPrologue() }, { - text: 'Upgrade', + text: "Yangilash", base: '/upgrade/', items: sidebarUpgrade() }, { - text: 'Getting Started', + text: "Boshlash", base: '/getting-started/', items: sidebarGettingStarted() }, { - text: 'Architecture Concepts', + text: "Arxitektura tushunchalari", base: '/architecture-concepts/', items: sidebarFoundation() }, { - text: 'The Basics', + text: "Asosiy tushunchalar", base: '/the-basics/', items: sidebarBasic() }, { - text: 'Digging Deeper', + text: "Chuqurroq o'rganish", base: '/digging-deeper/', items: sidebarAdvanced() }, { - text: 'Security', + text: "Xavfsizlik", base: '/security/', items: sidebarSecurity() }, { - text: 'Database', + text: "Ma'lumotlar bazasi", base: '/database/', items: sidebarDatabase() }, { @@ -41,51 +41,51 @@ export const config = defineConfig({ base: '/orm/', items: sidebarOrm() }, { - text: 'Testing', + text: "Testlash", base: '/testing/', items: sidebarTesting() }], editLink: { pattern: 'https://github.com/goravel/docs/edit/master/:path', - text: 'Edit this page on GitHub' + text: "Ushbu sahifani GitHub-da tahrirlash" }, footer: { - message: 'Released under the MIT License', - copyright: `Copyright © 2021-${new Date().getFullYear()} Goravel` + message: "MIT litsenziyasi ostida chiqarilgan", + copyright: `Mualliflik huquqi © 2021-${new Date().getFullYear()} Goravel` }, docFooter: { - prev: 'Previous page', - next: 'Next page' + prev: "Oldingi sahifa", + next: "Keyingi sahifa" }, outline: { - label: 'On this page' + label: "Ushbu sahifada" }, lastUpdated: { - text: 'Last updated', + text: "Oxirgi yangilanish", formatOptions: { - dateStyle: 'short', - timeStyle: 'medium' + dateStyle: "qisqa", + timeStyle: "o'rta" } }, - langMenuLabel: 'Change language', - returnToTopLabel: 'Return to top', - sidebarMenuLabel: 'Menu', - darkModeSwitchLabel: 'Appearance', - lightModeSwitchTitle: 'Switch to light theme', - darkModeSwitchTitle: 'Switch to dark theme', - skipToContentLabel: 'Skip to content' + langMenuLabel: "Tilni o'zgartirish", + returnToTopLabel: "Yuqoriga qaytish", + sidebarMenuLabel: "Menyu", + darkModeSwitchLabel: "Ko'rinish", + lightModeSwitchTitle: "Yorug‘lik mavzusiga o‘tish", + darkModeSwitchTitle: "Qorongʻu mavzuga oʻtish", + skipToContentLabel: "Kontentga o‘tish" } }); function nav(): DefaultTheme.NavItem[] { return [{ - text: 'Quickstart', + text: "Tez boshlash", link: '/getting-started/installation', activeMatch: '/getting-started/' }, { - text: 'Video Tutorials', + text: "Video darsliklar", link: 'https://www.youtube.com/playlist?list=PL40Xne4u-oXJ0Z5uFiPWHqIMvzZaG_BDf' }, { - text: 'Versions', + text: "Versiyalar", items: [{ text: "v1.17 (Eng so'nggi)", link: "" @@ -94,7 +94,7 @@ function nav(): DefaultTheme.NavItem[] { link: 'https://v116.goravel.dev/' }] }, { - text: 'Translate', + text: "Tarjima qilish", link: '/prologue/contributions#add-a-new-language' }]; } From e16cd0169063d15b698ae3e98f35fe42fd8f9743 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 30 Mar 2026 15:19:18 +0800 Subject: [PATCH 077/163] New translations en.ts (Uzbek) [skip ci] Update translations (Uzbek) en.ts --- .vitepress/config/uz_UZ.ts | 104 ++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/.vitepress/config/uz_UZ.ts b/.vitepress/config/uz_UZ.ts index 7e314c06a..0cd2e3f99 100644 --- a/.vitepress/config/uz_UZ.ts +++ b/.vitepress/config/uz_UZ.ts @@ -1,6 +1,6 @@ import { defineConfig, type DefaultTheme } from 'vitepress'; export const config = defineConfig({ - lang: 'en-US', + lang: "uz-UZ", description: "Goravel — bu to‘liq funksiyalarga ega va yuqori darajada kengaytiriladigan web-ilovalar frameworki hisoblanadi. U Go dasturchilari (gopherlar) uchun boshlang‘ich platforma (scaffolding) sifatida xizmat qiladi va ularga o‘z ilovalarini tez, tartibli va professional tarzda yaratishga yordam beradi.", themeConfig: { nav: nav(), @@ -100,61 +100,61 @@ function nav(): DefaultTheme.NavItem[] { } function sidebarGettingStarted(): DefaultTheme.SidebarItem[] { return [{ - text: 'Installation', + text: "O'rnatish", link: 'installation' }, { - text: 'Configuration', + text: "Konfiguratsiya", link: 'configuration' }, { - text: 'Directory Structure', + text: "Papka tuzilishi", link: 'directory-structure' }, { - text: 'Compile', + text: "Tuzish", link: 'compile' }, { - text: 'Excellent Packages', + text: "Ajoyib Paketlar", link: 'packages' }]; } function sidebarPrologue(): DefaultTheme.SidebarItem[] { return [{ - text: 'Release Notes', + text: "Chiqarish eslatmalari", link: 'releases' }, { - text: 'Contribution Guide', + text: "Hissa qo‘shish bo‘yicha qo‘llanma", link: 'contributions' }, { - text: 'Compare With Laravel', + text: "Laravel bilan solishtiring", link: 'compare-with-laravel' }, { - text: 'Privacy Policy', + text: "Maxfiylik siyosati", link: 'privacy' }]; } function sidebarUpgrade(): DefaultTheme.SidebarItem[] { return [{ - text: 'Upgrading To v1.17 From v1.16', + text: "v1.16-dan v1.17-ga yangilash", link: 'v1.17' }, { - text: 'Upgrading To v1.16 From v1.15', + text: "v1.15 dan v1.16 ga yangilash", link: 'v1.16' }, { - text: 'History', + text: "Tarix", link: 'history' }]; } function sidebarFoundation(): DefaultTheme.SidebarItem[] { return [{ - text: 'Lifecycle', + text: "Hayot sikli", link: 'request-lifecycle' }, { - text: 'Service Container', + text: "Xizmat konteyneri", link: 'service-container' }, { - text: 'Service Providers', + text: "Xizmat ko'rsatuvchilar", link: 'service-providers' }, { - text: 'Facades', + text: "Fasadlar", link: 'facades' }]; } @@ -166,127 +166,127 @@ function sidebarBasic(): DefaultTheme.SidebarItem[] { text: 'Middleware', link: 'middleware' }, { - text: 'Controllers', + text: "Kontrollerlar", link: 'controllers' }, { - text: 'Requests', + text: "So'rovlar", link: 'request' }, { - text: 'Responses', + text: "Javoblar", link: 'response' }, { - text: 'Views', + text: "Ko‘rishlar", link: 'views' }, { text: 'Grpc', link: 'grpc' }, { - text: 'Session', + text: "Seans", link: 'session' }, { - text: 'Validation', + text: "Tekshirish", link: 'validation' }, { - text: 'Logging', + text: "Loglash", link: 'logging' }]; } function sidebarAdvanced(): DefaultTheme.SidebarItem[] { return [{ - text: 'Artisan Console', + text: "Artisan Konsoli", link: 'artisan-console' }, { - text: 'Cache', + text: "Kesh", link: 'cache' }, { - text: 'Event', + text: "Harakat", link: 'event' }, { - text: 'File Storage', + text: "Fayl saqlash", link: 'filesystem' }, { - text: 'Mail', + text: "Pochta", link: 'mail' }, { - text: 'Queues', + text: "Navbatlar", link: 'queues' }, { - text: 'Task Scheduling', + text: "Vazifa rejalashtirish", link: 'task-scheduling' }, { - text: 'Localization', + text: "Lokallashtirish", link: 'localization' }, { - text: 'Package Development', + text: "Paketni ishlab chiqish", link: 'package-development' }, { - text: 'Color Output', + text: "Rang chiqishi", link: 'color' }, { - text: 'Processes', + text: "Jarayonlar", link: 'processes' }, { - text: 'Strings', + text: "Satrlar", link: 'strings' }, { - text: 'Helpers', + text: "Yordamchilar", link: 'helpers' }, { - text: 'HTTP Client', + text: "HTTP Klienti", link: 'http-client' }, { - text: 'Pluralization', + text: "Ko‘plik shakllari", link: 'pluralization' }]; } function sidebarSecurity(): DefaultTheme.SidebarItem[] { return [{ - text: 'Authentication', + text: "Autentifikatsiya", link: 'authentication' }, { - text: 'Authorization', + text: "Avtorizatsiya", link: 'authorization' }, { - text: 'Encryption', + text: "Shifrlash", link: 'encryption' }, { - text: 'Hashing', + text: "Xeshlash", link: 'hashing' }]; } function sidebarDatabase(): DefaultTheme.SidebarItem[] { return [{ - text: 'Getting Started', + text: "Boshlash", link: 'getting-started' }, { - text: 'Query Builder', + text: "So'rov quruvchi", link: 'queries' }, { - text: 'Migrations', + text: "Migratsiyalar", link: 'migrations' }, { - text: 'Seeding', + text: "Urg'ochish", link: 'seeding' }]; } function sidebarOrm(): DefaultTheme.SidebarItem[] { return [{ - text: 'Getting Started', + text: "Boshlash", link: 'getting-started' }, { - text: 'Relationships', + text: "Bog'lanishlar", link: 'relationships' }, { - text: 'Factories', + text: "Zavodlar", link: 'factories' }]; } function sidebarTesting(): DefaultTheme.SidebarItem[] { return [{ - text: 'Getting Started', + text: "Boshlash", link: 'getting-started' }, { - text: 'HTTP Tests', + text: "HTTP Testlari", link: 'http-tests' }, { text: 'Mock', From d623cd559a228288c8b38f322aec3d5766c9476e Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 30 Mar 2026 17:57:32 +0800 Subject: [PATCH 078/163] New translations facades.md (Uzbek) [skip ci] Update translations (Uzbek) facades.md --- uz_UZ/architecture-concepts/facades.md | 1 + 1 file changed, 1 insertion(+) diff --git a/uz_UZ/architecture-concepts/facades.md b/uz_UZ/architecture-concepts/facades.md index 9a5d99fa9..cd6f4cf12 100644 --- a/uz_UZ/architecture-concepts/facades.md +++ b/uz_UZ/architecture-concepts/facades.md @@ -10,6 +10,7 @@ import "app/facades" facades.Config().GetString("app.host") + ``` ## Fasadlar qanday ishlaydi From 67a92e8e1c288fc34f1ceada21504b3a41e96f29 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 30 Mar 2026 17:57:34 +0800 Subject: [PATCH 079/163] New translations service-container.md (Uzbek) [skip ci] Update translations (Uzbek) service-container.md --- .../service-container.md | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/uz_UZ/architecture-concepts/service-container.md b/uz_UZ/architecture-concepts/service-container.md index 8bbed269d..c4f6db47d 100644 --- a/uz_UZ/architecture-concepts/service-container.md +++ b/uz_UZ/architecture-concepts/service-container.md @@ -1,16 +1,16 @@ -# Service Container +# Xizmat Konteyneri [[toc]] -## Introduction +## Kirish -The Goravel service container is a powerful tool for managing class dependencies and performing dependency injection. It contains all the modules of Goravel, and allows you to bind your own services to container and resolve them when needed. The service container provides powerful support for third-party packages around Goravel. +Goravel xizmat konteyneri sinf bog'liqliklarini boshqarish va bog'liqlik in'ektsiyasini amalga oshirish uchun kuchli vosita hisoblanadi. U Goravelning barcha modullarini o'z ichiga oladi va sizga o'z xizmatlaringizni konteynerga bog'lash va kerak bo'lganda ularni hal qilish imkonini beradi. Xizmat konteyneri Goravel atrofidagi uchinchi tomon paketlari uchun kuchli qo'llab-quvvatlashni ta'minlaydi. -## Binding +## Bog'lash -### Simple Bindings +### Oddiy bog‘lamalar -Almost all of your service container bindings will be registered within [service providers](./service-providers.md). Within a service provider, you always have access to the container via the `app` parameter, then register a binding using the `Bind` method, passing the `key` that we wish to register along with a closure that returns an instance of the class: +Sizning xizmat konteyneringiz bog‘lanishlarining deyarli barchasi [xizmat provayderlari](./service-providers.md) ichida ro‘yxatdan o‘tkaziladi. Xizmat ko'rsatuvchi provayder ichida siz har doim konteynerga `app` parametri orqali kirishingiz mumkin, so'ngra `Bind` metodidan foydalanib bog'lashni ro'yxatdan o'tkazing, ro'yxatdan o'tkazmoqchi bo'lgan `key`ni va sinf namunasini qaytaruvchi yopilishni (closure) o'tkazing: ```go package route @@ -32,7 +32,7 @@ func (route *ServiceProvider) Register(app foundation.Application) { func (route *ServiceProvider) Boot(app foundation.Application) {} ``` -As mentioned, you will typically be interacting with the container within service providers; however, if you would like to interact with the container outside of a service provider, you may do so via the `App` facade: +Aytilganidek, odatda siz xizmat ko'rsatuvchi provayderlar ichida konteyner bilan ishlaysiz; biroq, agar siz xizmat ko'rsatuvchi provayderdan tashqarida konteyner bilan ishlashni istasangiz, `App` fasad orqali buni amalga oshirishingiz mumkin: ```go facades.App().Bind("key", func(app foundation.Application) (any, error) { @@ -40,27 +40,27 @@ facades.App().Bind("key", func(app foundation.Application) (any, error) { }) ``` -### Binding A Singleton +### Singleton bog'lash -The `Singleton` method binds a class or interface into the container that should only be resolved one time. Once a singleton binding is resolved, the same object instance will be returned on subsequent calls into the container: +`Singleton` usuli sinf yoki interfeysni konteynerga bir marta hal qilinishi kerak bo'lgan holda bog'laydi. Bir marta singleton bog'lash hal qilingandan so'ng, konteynerga keyingi chaqiruvlarda bir xil ob'ekt namunasi qaytariladi: ```go -app.Singleton(key, func(app foundation.Application) (any, error) { +app.Singleton(kalit, func(app foundation.Application) (any, error) { return NewGin(app.MakeConfig()), nil }) ``` -### Binding Instances +### Instanslarni bog'lash -You may also bind an existing object instance into the container using the `Instance` method. The given instance will always be returned on subsequent calls into the container: +Shuningdek, siz `Instance` usuli yordamida mavjud obyekt namunasini konteynerga bog‘lashingiz mumkin. Berilgan instansiya har doim konteynerga keyingi chaqiruvlarda qaytariladi: ```go app.Instance(key, instance) ``` -### Binding With Parameter +### Parametr bilan bog'lash -If you need some extra parameters to construct the service provider, you can use the `BindWith` method to pass parameters to the closure: +Agar xizmat provayderini yaratish uchun qo'shimcha parametrlar kerak bo'lsa, `BindWith` metodidan foydalanib, parametrlarni yopishga o'tkazishingiz mumkin: ```go app.BindWith(Binding, func(app foundation.Application, parameters map[string]any) (any, error) { @@ -68,30 +68,30 @@ app.BindWith(Binding, func(app foundation.Application, parameters map[string]any }) ``` -## Resolving +## Hal qilish -### The `Make` Method +### `Make` usuli -You may use the `Make` method to resolve a class instance from the container. The `Make` method accepts the `key` you wish to resolve: +Siz konteynerdan sinf namunasini hal qilish uchun `Make` metodidan foydalanishingiz mumkin. `Make` usuli siz hal qilmoqchi bo'lgan `key` ni qabul qiladi: ```go instance, err := app.Make(key) ``` -If you are outside of a service provider in a location of your code that does not have access to the `app` variable, you may use the `App` facade to resolve a class instance from the container: +Agar siz xizmat ko'rsatuvchi provayderdan tashqarida bo'lsangiz va kod joylashgan joyda `app` o'zgaruvchisiga kirish imkoni bo'lmasa, konteynerdan klass misolini olish uchun `App` fasadidan foydalanishingiz mumkin: ```go instance, err := facades.App().Make(key) ``` -### The `MakeWith` Method +### `MakeWith` metodi -If some of your class's dependencies are not resolvable via the container, you may inject them by passing them as an associative array into the `MakeWith` method, corresponding to the `BindWith` binding method: +Agar sinfingizning ba'zi bog'liqliklari konteyner orqali hal qilinmasa, ularni `BindWith` bog'lash usuliga mos ravishda `MakeWith` usuliga assotsiativ massiv sifatida o'tkazib, ularni kiritishingiz mumkin: ```go instance, err := app.MakeWith(key, map[string]any{"id": 1}) ``` -### Other Methods +### Boshqa uslublar -The framework provides some convenient methods to quickly resolve various facades: `MakeArtisan`, `MakeAuth`, etc. +Framework turli fasadlarni tez hal qilish uchun qulay usullarni taqdim etadi: `MakeArtisan`, `MakeAuth` va boshqalar. From d79afe1de6814c78c79f31a7ff8847d61bee6911 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 30 Mar 2026 17:57:36 +0800 Subject: [PATCH 080/163] New translations index.md (Uzbek) [skip ci] Update translations (Uzbek) index.md --- uz_UZ/index.md | 60 ++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/uz_UZ/index.md b/uz_UZ/index.md index 676e88296..e74f492a7 100644 --- a/uz_UZ/index.md +++ b/uz_UZ/index.md @@ -1,13 +1,13 @@ --- layout: home -title: Goravel - Full-featured Golang Development Framework +title: Goravel — Golang uchun to‘liq imkoniyatlarga ega zamonaviy freymvork head: - [ 'meta', { name: description, - content: Goravel is a Golang development framework with complete functions and excellent scalability. As a starting scaffolding to help Gopher quickly build their own applications. + content: Goravel - bu to'liq funksiyalarga ega va ajoyib kengaytirish imkoniyatiga ega bo'lgan Golang dasturlash freymvorkidir. Gopherlarning o'z ilovalarini tezda qurishiga yordam berish uchun boshlang'ich ishqalam sifatida. } ] - [ @@ -19,20 +19,20 @@ head: 'meta', { property: og:title, - content: Goravel - Full-featured Golang Development Framework + content: Goravel - To'liq imkoniyatli Golang Dasturlash Frameworki } ] - [ 'meta', { property: og:description, - content: Goravel is a Golang development framework with complete functions and excellent scalability. As a starting scaffolding to help Gopher quickly build their own applications. + content: Goravel - bu to'liq funksiyalar va ajoyib kengaytiriluvchanlikka ega Golang dasturlash ramkasi. Gopherlarning o'z ilovalarini tezda qurishiga yordam berish uchun boshlang'ich qolip sifatida. } ] - [ 'meta', { - property: og:image, + property: meta, content: https://www.goravel.dev/meta.png } ] @@ -52,14 +52,14 @@ head: 'meta', { name: twitter:title, - content: Goravel - The Golang Framework For Web Artisans + content: Goravel - Veb San'atkorlar Uchun Golang Frameworki } ] - [ 'meta', { name: twitter:description, - content: Goravel is a Golang development framework with complete functions and excellent scalability. As a starting scaffolding to help Gopher quickly build their own applications. + content: Goravel - bu to'liq funksiyalarga ega va ajoyib kengaytiriladigan Golang dasturlash tizimidir. Gopherlarning o'z ilovalarini tezda qurishlariga yordam berish uchun boshlang'ich iskala sifatida. } ] - [ @@ -72,33 +72,33 @@ head: hero: name: Goravel - text: Full-featured Golang Development Framework - tagline: Componentization, High-performance, easy-to-extend, PHPers' first choice. + text: To'liq xususiyatli Golang dasturlash freymvorki + tagline: Komponentlashtirish, yuqori samaradorlik, kengaytirish oson, PHP dasturchilarining birinchi tanlovi. # image: /logo.svg actions: - theme: brand - text: Quick Start + text: Tezda boshlash link: /getting-started/installation - theme: alt text: 🌟 Github Star link: https://github.com/goravel/goravel target: _blank features: - - title: 🧰 Lite Or Full-featured - details: You can choose between a lightweight version with essential features or a full-featured version that includes ORM, HTTP, logging, caching, and other basic tools for all development. - - title: 💻 Componentization - details: Modular design, each module is independent and can be used separately, making development and maintenance more convenient. - - title: 🚀 High-performance - details: Built with Golang, integrating multiple excellent extensions to create fast and responsive applications. - - title: 📈 Easy-to-extend - details: The module provides multiple drivers, and can develop extension packages according to needs, suitable for applications of any scale, from small projects to large systems. - - title: 👥 Active community - details: Supported by an active community, they contribute to its development, documentation, and continuous support. - - title: 🔄 PHPers' first choice - details: The framework style is consistent with Laravel, allowing PHPer to create powerful Golang applications without learning a new framework. Tribute to Laravel! + - title: 🧰 Yengil yoki to'liq imkoniyatli + details: Siz zaruriy xususiyatlarga ega bo'lgan yengil versiya yoki ORM, HTTP, jurnal, keshlash va boshqa barcha ishlanmalar uchun asosiy vositalarni o'z ichiga olgan to'liq xususiyatli versiya o'rtasida tanlashingiz mumkin. + - title: 💻 Komponentlashtirish + details: Modul dizayni, har bir modul mustaqil va alohida ishlatilishi mumkin, bu esa ishlab chiqish va texnik xizmat ko'rsatishni qulayroq qiladi. + - title: 🚀 Yuqori samaradorlik + details: Golang bilan qurilgan, tez va sezgir ilovalar yaratish uchun bir nechta ajoyib kengaytmalarni birlashtiradi. + - title: 📈 Kengaytirish oson + details: Modul bir nechta haydovchilarni taqdim etadi va ehtiyojlarga qarab kengaytirish paketlarini ishlab chiqishi mumkin, kichik loyihalardan tortib katta tizimlargacha bo'lgan har qanday o'lchamdagi ilovalar uchun mos keladi. + - title: 👥 Faol hamjamiyat + details: Faol hamjamiyat tomonidan qo'llab-quvvatlanadi, ular uning rivojlanishi, hujjatlashtirilishi va doimiy qo'llab-quvvatlashiga hissa qo'shadi. + - title: 🔄 PHP dasturchilarning birinchi tanlovi + details: Freymvork uslubi Laravel bilan muvofiq, PHP dasturchilariga yangi framework o'rganmasdan kuchli Golang ilovalarini yaratish imkonini beradi. Laravelga hurmat! --- -
Contributors
+
Hissa qo'shganlar
@@ -143,38 +143,36 @@ features:
-
Group
+
Guruh
-
Scan QR code to join the Wechat group
+
Wechat guruhiga qo'shilish uchun QR kodni skanerlang
- -
Click me to join the Discord group
+
Discord guruhiga qo'shilish uchun menga bosing
-
Reward
+
Mukofot
-
Scan QR code by Wechat
+
Wechat orqali QR kodni skanerlash
From 6a055116b61494f60be2bf470a7efb247242c77e Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 30 Mar 2026 21:46:37 +0800 Subject: [PATCH 081/163] New translations readme.md (Uzbek) [skip ci] Update translations (Uzbek) readme.md --- uz_UZ/README.md | 182 +++++++++++++++++++++++++++++------------------- 1 file changed, 109 insertions(+), 73 deletions(-) diff --git a/uz_UZ/README.md b/uz_UZ/README.md index e7dccf1e6..a046117e4 100644 --- a/uz_UZ/README.md +++ b/uz_UZ/README.md @@ -2,100 +2,136 @@ Logo -[![Doc](https://pkg.go.dev/badge/github.com/goravel/framework)](https://pkg.go.dev/github.com/goravel/framework) +[![Hujjat](https://pkg.go.dev/badge/github.com/goravel/framework)](https://pkg.go.dev/github.com/goravel/framework) [![Go](https://img.shields.io/github/go-mod/go-version/goravel/framework)](https://go.dev/) -[![Release](https://img.shields.io/github/release/goravel/framework.svg)](https://github.com/goravel/framework/releases) +[![Reliz](https://img.shields.io/github/release/goravel/framework.svg)](https://github.com/goravel/framework/releases) [![Test](https://github.com/goravel/framework/actions/workflows/test.yml/badge.svg)](https://github.com/goravel/framework/actions) -[![Report Card](https://goreportcard.com/badge/github.com/goravel/framework)](https://goreportcard.com/report/github.com/goravel/framework) +[![Hisobot kartasi](https://goreportcard.com/badge/github.com/goravel/framework)](https://goreportcard.com/report/github.com/goravel/framework) [![Codecov](https://codecov.io/gh/goravel/framework/branch/master/graph/badge.svg)](https://codecov.io/gh/goravel/framework) -![License](https://img.shields.io/github/license/goravel/framework) +![Litsenziya](https://img.shields.io/github/license/goravel/framework)
-English | [中文](/zh_CN/README.md) - -## About Goravel - -Goravel is a full-featured, scalable web application framework that provides a starting scaffold to help Gophers quickly build their applications. - -The framework style is consistent with [Laravel](https://laravel.com/), so PHP developers don’t need to learn a new framework and can still enjoy playing around with Golang, in tribute to Laravel! - -We welcome stars, PRs, and issues! - -## Documentation - -Online documentation [https://www.goravel.dev](https://www.goravel.dev) - -Example [https://github.com/goravel/example](https://github.com/goravel/example) - -> To optimize the documentation, please submit a PR to the documentation -> repository [https://github.com/goravel/docs](https://github.com/goravel/docs) - -## Main Features - -| Module Name | Description | -| -------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | -| [Artisan Console](https://www.goravel.dev/digging-deeper/artisan-console.html) | CLI command-line interface for application management and automation | -| [Authentication](https://www.goravel.dev/security/authentication.html) | User identity verification with JWT and Session drivers | -| [Authorization](https://www.goravel.dev/security/authorization.html) | Permission-based access control using policies and gates | -| [Cache](https://www.goravel.dev/digging-deeper/cache.html) | Store and retrieve data using memory, Redis, or custom drivers | -| [Carbon](https://www.goravel.dev/digging-deeper/helpers.html) | Helper functions for date and time manipulation | -| [Config](https://www.goravel.dev/getting-started/configuration.html) | Application configuration management from files and environment | -| [Crypt](https://www.goravel.dev/security/encryption.html) | Secure data encryption and decryption utilities | -| [DB](https://www.goravel.dev/database/getting-started.html) | Database query builder | -| [Event](https://www.goravel.dev/digging-deeper/event.html) | Application event dispatching and listening system | -| [Factory](https://www.goravel.dev/orm/factories.html) | Generate fake model data for testing purposes | -| [FileStorage](https://www.goravel.dev/digging-deeper/filesystem.html) | File upload, download, and storage across multiple drivers | -| [Grpc](https://www.goravel.dev/the-basics/grpc.html) | High-performance gRPC server and client implementation | -| [Hash](https://www.goravel.dev/security/hashing.html) | Secure password hashing | -| [Http](https://www.goravel.dev/the-basics/routing.html) | HTTP routing, controllers, and middleware management | -| [Http Client](https://www.goravel.dev/digging-deeper/http-client.html) | Make HTTP requests to external APIs and services | -| [Localization](https://www.goravel.dev/digging-deeper/localization.html) | Multi-language translation and locale management | -| [Logger](https://www.goravel.dev/the-basics/logging.html) | Application logging to files, console, or external services | -| [Mail](https://www.goravel.dev/digging-deeper/mail.html) | Send emails via SMTP or queue-based delivery | -| [Mock](https://www.goravel.dev/testing/mock.html) | Create test mocks for facades and dependencies | -| [Migrate](https://www.goravel.dev/database/migrations.html) | Version control for database schema changes | -| [Orm](https://www.goravel.dev/orm/getting-started.html) | Elegant Orm implementation for database operations | -| [Package Development](https://www.goravel.dev/digging-deeper/package-development.html) | Build reusable packages to extend framework functionality | -| [Process](https://www.goravel.dev/digging-deeper/process.html) | An expressive and elegant API around Go's standard `os/exec` package | -| [Queue](https://www.goravel.dev/digging-deeper/queues.html) | Defer time-consuming tasks to background job processing | -| [Seeder](https://www.goravel.dev/database/seeding.html) | Populate database tables with test or initial data | -| [Session](https://www.goravel.dev/the-basics/session.html) | Manage user session data across HTTP requests | -| [Task Scheduling](https://www.goravel.dev/digging-deeper/task-scheduling.html) | Schedule recurring tasks using cron-like expressions | -| [Testing](https://www.goravel.dev/testing/getting-started.html) | HTTP testing, mocking, and assertion utilities | -| [Validation](https://www.goravel.dev/the-basics/validation.html) | Validate incoming request data using rules | -| [View](https://www.goravel.dev/the-basics/views.html) | Template rendering engine for HTML responses | +Inglizcha | [Xitoycha](/zh_CN/README.md) + +## Goravel haqida + +Goravel - bu Gopherlar o'z ilovalarini tezda qurishlariga yordam berish uchun boshlang'ich qolipni taqdim etadigan, to'liq imkoniyatli, masshtablanadigan veb-ilova freymvorkidir. + +Freymvork uslubi [Laravel](https://laravel.com/) bilan mos keladi, shuning uchun PHP dasturchilari yangi reymvorkni o‘rganishga muhtoj emas va Golang bilan ishlashdan zavqlanishlari mumkin, Laravelga hurmat bilan! + +Biz yulduzlar, PR-lar va muammolarni qabul qilamiz! + +## Hujjatlar + +Onlayn hujjatlar [https://www.goravel.dev](https://www.goravel.dev) + +Namuna [https://github.com/goravel/example](https://github.com/goravel/example) + +> Hujjatni optimallashtirish uchun iltimos, hujjatlar omboriga PR yuboring [https://github.com/goravel/docs](https://github.com/goravel/docs) + +## Asosiy belgilari + +| Modul nomi | Tavsifi | +| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | +| [Artisan Console](https://www.goravel.dev/digging-deeper/artisan-console.html) | Ilova boshqaruvi va avtomatlashtirish uchun CLI buyruq qatori interfeysi | +| [Authentication](https://www.goravel.dev/security/authentication.html) | Foydalanuvchi identifikatsiyasini JWT va Session haydovchilari bilan tekshirish | +| [Authorization](https://www.goravel.dev/security/authorization.html) | Siyosat va darvozalar yordamida ruxsat asosidagi kirish nazorati | +| [Cache](https://www.goravel.dev/digging-deeper/cache.html) | Ma'lumotlarni xotira, Redis yoki maxsus drayverlar yordamida saqlang va oling | +| [Carbon](https://www.goravel.dev/digging-deeper/helpers.html) | Sana va vaqt manipulyatsiyasi uchun yordamchi funksiyalar | +| [Konfiguratsiya](https://www.goravel.dev/getting-started/configuration.html) | Fayllar va muhitdan ilova konfiguratsiyasini boshqarish | +| [Kriptlash](https://www.goravel.dev/security/encryption.html) | Xavfsiz ma'lumotlarni shifrlash va shifrdan ochish vositalari | +| [MB](https://www.goravel.dev/database/getting-started.html) | Ma'lumotlar bazasi so'rov quruvchisi | +| [Hodisa](https://www.goravel.dev/digging-deeper/event.html) | Ilova hodisalarini tarqatish va tinglash tizimi | +| [Factory](https://www.goravel.dev/orm/factories.html) | Generate fake model data for testing purposes | +| [FileStorage](https://www.goravel.dev/digging-deeper/filesystem.html) | File upload, download, and storage across multiple drivers | +| [Grpc](https://www.goravel.dev/the-basics/grpc.html) | High-performance gRPC server and client implementation | +| [Hash](https://www.goravel.dev/security/hashing.html) | Secure password hashing | +| [Http](https://www.goravel.dev/the-basics/routing.html) | HTTP routing, controllers, and middleware management | +| [Http Client](https://www.goravel.dev/digging-deeper/http-client.html) | Make HTTP requests to external APIs and services | +| [Localization](https://www.goravel.dev/digging-deeper/localization.html) | Multi-language translation and locale management | +| [Logger](https://www.goravel.dev/the-basics/logging.html) | Application logging to files, console, or external services | +| [Mail](https://www.goravel.dev/digging-deeper/mail.html) | Send emails via SMTP or queue-based delivery | +| [Mock](https://www.goravel.dev/testing/mock.html) | Create test mocks for facades and dependencies | +| [Migrate](https://www.goravel.dev/database/migrations.html) | Version control for database schema changes | +| [Orm](https://www.goravel.dev/orm/getting-started.html) | Elegant Orm implementation for database operations | +| [Package Development](https://www.goravel.dev/digging-deeper/package-development.html) | Build reusable packages to extend framework functionality | +| [Process](https://www.goravel.dev/digging-deeper/process.html) | An expressive and elegant API around Go's standard `os/exec` package | +| [Queue](https://www.goravel.dev/digging-deeper/queues.html) | Defer time-consuming tasks to background job processing | +| [Seeder](https://www.goravel.dev/database/seeding.html) | Populate database tables with test or initial data | +| [Session](https://www.goravel.dev/the-basics/session.html) | Manage user session data across HTTP requests | +| [Task Scheduling](https://www.goravel.dev/digging-deeper/task-scheduling.html) | Schedule recurring tasks using cron-like expressions | +| [Testing](https://www.goravel.dev/testing/getting-started.html) | HTTP testing, mocking, and assertion utilities | +| [Validation](https://www.goravel.dev/the-basics/validation.html) | Validate incoming request data using rules | +| [View](https://www.goravel.dev/the-basics/views.html) | Template rendering engine for HTML responses | ## Compare With Laravel [For Detail](https://www.goravel.dev/prologue/compare-with-laravel.html) -## Roadmap +## Yo'l xaritasi -[For Detail](https://github.com/goravel/goravel/issues?q=is%3Aissue+is%3Aopen) +[Tafsilot uchun](https://github.com/goravel/goravel/issues?q=is%3Aissue+is%3Aopen) -## Excellent Extend Packages +## Ajoyib Kengaytiruvchi Paketlar [For Detail](https://www.goravel.dev/getting-started/packages.html) -## Contributors - -This project is made possible by everyone who contributes. To contribute, please consult the [Contribution Guide](prologue/contributions.md). - - - -## Sponsor - -Better development of the project is inseparable from your support, reward us by [Open Collective](https://opencollective.com/goravel). +## Hissa qo'shuvchilar + +Bu loyiha har bir hissa qo'shgan insonlar tufayli amalga oshirildi. To contribute, please consult the [Contribution Guide](prologue/contributions.md). + +<0><1> +<2><3> +<4><5> +<6><7> +<8><9> +<10><11> +<12><13> +<14><15> +<16><17> +<18><19> +<20><21> +<22><23> +<24><25> +<26><27> +<28><29> +<30><31> +<32><33> +<34><35> +<36><37> +<38><39> +<40><41> +<42><43> +<44><45> +<46><47> +<48><49> +<50><51> +<52><53> +<54><55> +<56><57> +<58><59> +<60><61> +<62><63> +<64><65> +<66><67> +<68><69> +<70><71> +<72><73> +<74><75> + +## Homiylar + +Loyihaning yaxshi rivojlanishi sizning qo‘llab-quvvatlashingizsiz bo‘lmaydi, bizni [Open Collective](https://opencollective.com/goravel) orqali mukofotlang.

-## Group +## Guruh -Welcome more discussion in Discord. +Discordda ko'proq muhokamani xush ko'ramiz. [https://discord.gg/cFc5csczzS](https://discord.gg/cFc5csczzS) -## License +## Litsenziya -The Goravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). +Goravel frameworki MIT litsenziyasi ostida litsenziyalangan ochiq manbali dasturiy ta'minotdir [MIT litsenziyasi](https://opensource.org/licenses/MIT). From d3671c7dc56942639456e297fc86080ea4108959 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 30 Mar 2026 23:27:16 +0800 Subject: [PATCH 082/163] New translations readme.md (Uzbek) [skip ci] Update translations (Uzbek) readme.md --- uz_UZ/README.md | 76 ++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/uz_UZ/README.md b/uz_UZ/README.md index a046117e4..42fa30f8f 100644 --- a/uz_UZ/README.md +++ b/uz_UZ/README.md @@ -32,42 +32,42 @@ Namuna [https://github.com/goravel/example](https://github.com/goravel/example) ## Asosiy belgilari -| Modul nomi | Tavsifi | -| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | -| [Artisan Console](https://www.goravel.dev/digging-deeper/artisan-console.html) | Ilova boshqaruvi va avtomatlashtirish uchun CLI buyruq qatori interfeysi | -| [Authentication](https://www.goravel.dev/security/authentication.html) | Foydalanuvchi identifikatsiyasini JWT va Session haydovchilari bilan tekshirish | -| [Authorization](https://www.goravel.dev/security/authorization.html) | Siyosat va darvozalar yordamida ruxsat asosidagi kirish nazorati | -| [Cache](https://www.goravel.dev/digging-deeper/cache.html) | Ma'lumotlarni xotira, Redis yoki maxsus drayverlar yordamida saqlang va oling | -| [Carbon](https://www.goravel.dev/digging-deeper/helpers.html) | Sana va vaqt manipulyatsiyasi uchun yordamchi funksiyalar | -| [Konfiguratsiya](https://www.goravel.dev/getting-started/configuration.html) | Fayllar va muhitdan ilova konfiguratsiyasini boshqarish | -| [Kriptlash](https://www.goravel.dev/security/encryption.html) | Xavfsiz ma'lumotlarni shifrlash va shifrdan ochish vositalari | -| [MB](https://www.goravel.dev/database/getting-started.html) | Ma'lumotlar bazasi so'rov quruvchisi | -| [Hodisa](https://www.goravel.dev/digging-deeper/event.html) | Ilova hodisalarini tarqatish va tinglash tizimi | -| [Factory](https://www.goravel.dev/orm/factories.html) | Generate fake model data for testing purposes | -| [FileStorage](https://www.goravel.dev/digging-deeper/filesystem.html) | File upload, download, and storage across multiple drivers | -| [Grpc](https://www.goravel.dev/the-basics/grpc.html) | High-performance gRPC server and client implementation | -| [Hash](https://www.goravel.dev/security/hashing.html) | Secure password hashing | -| [Http](https://www.goravel.dev/the-basics/routing.html) | HTTP routing, controllers, and middleware management | -| [Http Client](https://www.goravel.dev/digging-deeper/http-client.html) | Make HTTP requests to external APIs and services | -| [Localization](https://www.goravel.dev/digging-deeper/localization.html) | Multi-language translation and locale management | -| [Logger](https://www.goravel.dev/the-basics/logging.html) | Application logging to files, console, or external services | -| [Mail](https://www.goravel.dev/digging-deeper/mail.html) | Send emails via SMTP or queue-based delivery | -| [Mock](https://www.goravel.dev/testing/mock.html) | Create test mocks for facades and dependencies | -| [Migrate](https://www.goravel.dev/database/migrations.html) | Version control for database schema changes | -| [Orm](https://www.goravel.dev/orm/getting-started.html) | Elegant Orm implementation for database operations | -| [Package Development](https://www.goravel.dev/digging-deeper/package-development.html) | Build reusable packages to extend framework functionality | -| [Process](https://www.goravel.dev/digging-deeper/process.html) | An expressive and elegant API around Go's standard `os/exec` package | -| [Queue](https://www.goravel.dev/digging-deeper/queues.html) | Defer time-consuming tasks to background job processing | -| [Seeder](https://www.goravel.dev/database/seeding.html) | Populate database tables with test or initial data | -| [Session](https://www.goravel.dev/the-basics/session.html) | Manage user session data across HTTP requests | -| [Task Scheduling](https://www.goravel.dev/digging-deeper/task-scheduling.html) | Schedule recurring tasks using cron-like expressions | -| [Testing](https://www.goravel.dev/testing/getting-started.html) | HTTP testing, mocking, and assertion utilities | -| [Validation](https://www.goravel.dev/the-basics/validation.html) | Validate incoming request data using rules | -| [View](https://www.goravel.dev/the-basics/views.html) | Template rendering engine for HTML responses | - -## Compare With Laravel - -[For Detail](https://www.goravel.dev/prologue/compare-with-laravel.html) +| Modul nomi | Tavsifi | +| ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | +| [Artisan Console](https://www.goravel.dev/digging-deeper/artisan-console.html) | Ilova boshqaruvi va avtomatlashtirish uchun CLI buyruq qatori interfeysi | +| [Authentication](https://www.goravel.dev/security/authentication.html) | Foydalanuvchi identifikatsiyasini JWT va Session haydovchilari bilan tekshirish | +| [Authorization](https://www.goravel.dev/security/authorization.html) | Siyosat va darvozalar yordamida ruxsat asosidagi kirish nazorati | +| [Cache](https://www.goravel.dev/digging-deeper/cache.html) | Ma'lumotlarni xotira, Redis yoki maxsus drayverlar yordamida saqlang va oling | +| [Carbon](https://www.goravel.dev/digging-deeper/helpers.html) | Sana va vaqt manipulyatsiyasi uchun yordamchi funksiyalar | +| [Konfiguratsiya](https://www.goravel.dev/getting-started/configuration.html) | Fayllar va muhitdan ilova konfiguratsiyasini boshqarish | +| [Kriptlash](https://www.goravel.dev/security/encryption.html) | Xavfsiz ma'lumotlarni shifrlash va shifrdan ochish vositalari | +| [MB](https://www.goravel.dev/database/getting-started.html) | Ma'lumotlar bazasi so'rov quruvchisi | +| [Hodisa](https://www.goravel.dev/digging-deeper/event.html) | Ilova hodisalarini tarqatish va tinglash tizimi | +| [Fabrika](https://www.goravel.dev/orm/factories.html) | Test maqsadlari uchun soxta model ma'lumotlarini yaratish | +| [FileStorage](https://www.goravel.dev/digging-deeper/filesystem.html) | Fayl yuklash, yuklab olish va bir nechta haydovchilar orqali saqlash | +| [Grpc](https://www.goravel.dev/the-basics/grpc.html) | Yuqori samaradorlikdagi gRPC server va mijoz amalga oshirilishi | +| [Hash](https://www.goravel.dev/security/hashing.html) | Xavfsiz parol xeshlash | +| [Http](https://www.goravel.dev/the-basics/routing.html) | HTTP marshrutlash, kontrollerlar va middleware boshqaruv | +| [Http Client](https://www.goravel.dev/digging-deeper/http-client.html) | Tashqi API va xizmatlarga HTTP so‘rovlarni amalga oshiring | +| [Lokalizatsiya](https://www.goravel.dev/digging-deeper/localization.html) | Ko'p tilli tarjima va til sozlamalarini boshqarish | +| [Logger](https://www.goravel.dev/the-basics/logging.html) | Ilovalarni fayllarga, konsolga yoki tashqi xizmatlarga yozish | +| [Pochta](https://www.goravel.dev/digging-deeper/mail.html) | SMTP or navbatga asoslangan yetkazib berish orqali elektron pochta xabarlarini yuboring | +| [Mock](https://www.goravel.dev/testing/mock.html) | Create test mocks for facades and dependencies | +| [Migrate](https://www.goravel.dev/database/migrations.html) | Ma'lumotlar bazasi sxemasi o'zgarishlari uchun versiyalarni boshqarish | +| [Orm](https://www.goravel.dev/orm/getting-started.html) | Ma'lumotlar bazasi operatsiyalari uchun nafis Orm amalga oshirilishi | +| [Paketni Ishlab Chiqish](https://www.goravel.dev/digging-deeper/package-development.html) | Freymvork funksiyalarini kengaytirish uchun qayta ishlatiladigan paketlar yarating | +| [Jarayon](https://www.goravel.dev/digging-deeper/process.html) | Go standart `os/exec` paketi atrofida ifodali va nafis API | +| [Navbat](https://www.goravel.dev/digging-deeper/queues.html) | Vaqt talab qiladigan vazifalarni orqa fondagi ish jarayoniga topshirish | +| [Seeder](https://www.goravel.dev/database/seeding.html) | Ma'lumotlar bazasi jadvallarini sinov yoki boshlang'ich ma'lumotlar bilan to'ldiring | +| [Sessiya](https://www.goravel.dev/the-basics/session.html) | HTTP so'rovlari bo'ylab foydalanuvchi sessiyasi ma'lumotlarini boshqarish | +| [Vazifa rejalashtirish](https://www.goravel.dev/digging-deeper/task-scheduling.html) | Cron-ga o'xshash ifodalar yordamida takrorlanuvchi vazifalarni rejalashtiring | +| [Testlash](https://www.goravel.dev/testing/getting-started.html) | HTTP testlash, mocklash va tasdiqlash vositalari | +| [Tekshirish](https://www.goravel.dev/the-basics/validation.html) | Qoidalardan foydalanib kiruvchi so'rov ma'lumotlarini tekshirish | +| [Koʻrish](https://www.goravel.dev/the-basics/views.html) | HTML javoblar uchun shablonlarni ko'rsatish dvigateli | + +## Laravel bilan solishtiring + +[Batafsil ma'lumot uchun](https://www.goravel.dev/prologue/compare-with-laravel.html) ## Yo'l xaritasi @@ -75,11 +75,11 @@ Namuna [https://github.com/goravel/example](https://github.com/goravel/example) ## Ajoyib Kengaytiruvchi Paketlar -[For Detail](https://www.goravel.dev/getting-started/packages.html) +[Tafsilotlar uchun](https://www.goravel.dev/getting-started/packages.html) ## Hissa qo'shuvchilar -Bu loyiha har bir hissa qo'shgan insonlar tufayli amalga oshirildi. To contribute, please consult the [Contribution Guide](prologue/contributions.md). +Bu loyiha har bir hissa qo'shgan insonlar tufayli amalga oshirildi. Hisob qilish uchun, iltimos, [Hisob qilish Qo‘llanmasi](prologue/contributions.md) bilan maslahatlashing. <0><1> <2><3> From fbd61dcc15e926712165c890c8b661016c1670d2 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Tue, 31 Mar 2026 14:56:05 +0800 Subject: [PATCH 083/163] New translations service-providers.md (Uzbek) [skip ci] Update translations (Uzbek) service-providers.md --- .../service-providers.md | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/uz_UZ/architecture-concepts/service-providers.md b/uz_UZ/architecture-concepts/service-providers.md index a1c4a3efc..790987074 100644 --- a/uz_UZ/architecture-concepts/service-providers.md +++ b/uz_UZ/architecture-concepts/service-providers.md @@ -1,24 +1,24 @@ -# Service Providers +# Xizmat ko'rsatuvchilar [[toc]] -## Introduction +## Kirish -The most important thing in the kernel boot operation is to load the `ServiceProvider`. All `ServiceProvider` under the application are configured in the `bootstrap/providers.go` file. +Yadro ishga tushirish operatsiyasida eng muhim narsa `ServiceProvider`ni yuklashdir. Ilovaning barcha `ServiceProvider`lari `bootstrap/providers.go` faylida sozlanadi. -First, the kernel will call the `Register` method of all service providers. After all service providers have been registered, the kernel will call the `Boot` method of all `ServiceProvider` again. +Avvalo, yadro barcha xizmat ko'rsatuvchilarning `Register` metodini chaqiradi. Barcha xizmat ko'rsatuvchilar ro'yxatdan o'tkazilgandan so'ng, yadro barcha `ServiceProvider`larning `Boot` metodini yana chaqiradi. -The `ServiceProvider` is the key to the life cycle of Goravel. They enable the framework to contain various components, such as routing, database, queue, cache, etc. +`ServiceProvider` Goravel hayot tsiklining kalitidir. Ular freymvorkga turli komponentlarni, masalan, marshrutlash, ma'lumotlar bazasi, navbat, keshlash va hokazolarni o'z ichiga olish imkonini beradi. -## Create Service Provider +## Xizmat ko'rsatuvchini yaratish -Service providers contain a `Register` and a `Boot` method. Within the `Register` method, you should only bind things into [the service container](./service-container.md). You should never attempt to register any event listeners, routes, or any other piece of functionality within the `Register` method, use the `Boot` method for that. +Xizmat ko'rsatuvchilar `Register` va `Boot` usullarini o'z ichiga oladi. `Register` usulida siz faqat [xizmat konteyneriga](./service-container.md) narsalarni bog'lashingiz kerak. Siz hech qachon `Register` usulida hech qanday hodisa tinglovchilarini, marshrutlarni yoki boshqa funksionallikni ro'yxatdan o'tkazishga urinmang, buning uchun `Boot` usulidan foydalaning. ```bash -./artisan make:provider YourServiceProviderName +./artisan make:provider SizningXizmatKo‘rsatuvchiProvayderingizNomi ``` -The Artisan CLI can generate a new provider via the `make:provider` command. The new service provider will be registered automatically in the `bootstrap/providers.go::Providers()` function and the function will be called by `WithProviders`. +Artisan CLI `make:provider` buyrug'i orqali yangi provayder yaratish mumkin. Yangi xizmat ko'rsatuvchi provayder `bootstrap/providers.go::Providers()` funksiyasida avtomatik ravishda ro'yxatdan o'tkaziladi va funksiya `WithProviders` tomonidan chaqiriladi. ```go func Boot() contractsfoundation.Application { @@ -31,7 +31,7 @@ func Boot() contractsfoundation.Application { ## Dependency Relationship -`ServiceProvider` provides an optional method `Relationship() binding.Relationship`, used to declare the dependency relationship, the `ServiceProvider` that sets this method will not depend on the registration order, and the `ServiceProvider` that does not set it will be registered last, for example: +`ServiceProvider` `Relationship()` ixtiyoriy usulini taqdim etadi `binding.Relationship`, bog'liqlik munosabatini e'lon qilish uchun ishlatiladi, ushbu usulni o'rnatgan `ServiceProvider` ro'yxatga olish tartibiga bog'liq bo'lmaydi, va uni o'rnatmagan `ServiceProvider` oxirgi ro'yxatga olinadi, masalan: ```go type ServiceProvider struct {} @@ -59,11 +59,11 @@ func (r *ServiceProvider) Register(app foundation.Application) { func (r *ServiceProvider) Boot(app foundation.Application) {} ``` -## Runners +## Ishlovchilar -The `ServiceProvider` can also implement the `Runners` interface to run some code when the application starts. It's usually used to start/shutdown the service which is defined in the `ServiceProvider`. For example: `Route`, `Schedule`, `Queue`, etc. You don't need to start/shutdown these services with `Runners` in the `main.go` anymore, Goravel will take care of it. +`ServiceProvider` ilovani ishga tushirishda ba'zi kodlarni ishga tushirish uchun `Runners` interfeysini ham amalga oshirishi mumkin. Bu odatda `ServiceProvider` da aniqlangan xizmatni ishga tushirish yoki o'chirish uchun ishlatiladi. Masalan: `Route`, `Schedule`, `Queue`, va boshqalar. Endi siz bu xizmatlarni `main.go` faylidagi `Runners` bilan ishga tushirish/to‘xtatish shart emas, Goravel buning o‘zini qiladi. -A `Runner` contains three methods: `ShouldRun()`, `Run()`, and `Shutdown()`. +`Runner` uchta usulni o'z ichiga oladi: `ShouldRun()`, `Run()`, va `Shutdown()`. ```go type Runner interface { @@ -76,7 +76,7 @@ type Runner interface { } ``` -There is an example of a `RouteRunner` defined in the `ServiceProvider` to start and shutdown the `Route` service. +`ServiceProvider` ichida `Route` xizmatini ishga tushirish va o‘chirish uchun aniqlangan `RouteRunner` misoli mavjud. ```go type ServiceProvider struct {} @@ -123,7 +123,7 @@ func (r *RouteRunner) Shutdown() error { } ``` -You can register your own `Runner` in the `bootstrap/app.go::WithRunners` function to run some code when the application starts. +Ilovani ishga tushirishda ba'zi kodni ishga tushirish uchun `bootstrap/app.go::WithRunners` funksiyasida o'zingizning `Runner`ingizni ro'yxatdan o'tkazishingiz mumkin. ```go func Boot() contractsfoundation.Application { From 6c6d0cd360e6a98d1e2552b6e7f38feec803bacd Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Tue, 31 Mar 2026 16:37:49 +0800 Subject: [PATCH 084/163] New translations getting-started.md (Uzbek) [skip ci] Update translations (Uzbek) getting-started.md --- uz_UZ/database/getting-started.md | 98 +++++++++++++++---------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/uz_UZ/database/getting-started.md b/uz_UZ/database/getting-started.md index f4bc83ad7..894685198 100644 --- a/uz_UZ/database/getting-started.md +++ b/uz_UZ/database/getting-started.md @@ -1,36 +1,36 @@ -# Getting Started +# Boshlash [[toc]] -## Introduction +## Kirish -Almost all applications need to interact with databases, so Goravel provides a very simple and easy-to-use database interaction. Developers can use native SQL, query builder, and [Orm](../orm/getting-started) to interact with databases. Currently, Goravel provides official support for the following four databases: +Deyarli barcha ilovalar ma'lumotlar bazalari bilan o'zaro aloqada bo'lishi kerak, shuning uchun Goravel juda oddiy va qulay ma'lumotlar bazasi o'zaro aloqasini taqdim etadi. Dasturchilar ma'lumotlar bazalari bilan ishlash uchun native SQL, so'rov quruvchi va [Orm](../orm/getting-started) dan foydalanishlari mumkin. Hozirda Goravel quyidagi to'rtta ma'lumotlar bazasini rasmiy qo'llab-quvvatlaydi: -| Database | Driver | -| ---------- | ------------------------------------------------------------------------------------ | -| PostgreSQL | [github.com/goravel/postgres](https://github.com/goravel/postgres) | -| MySQL | [github.com/goravel/mysql](https://github.com/goravel/mysql) | -| SQL Server | [github.com/goravel/sqlserver](https://github.com/goravel/sqlserver) | -| SQLite | [github.com/goravel/sqlite](https://github.com/goravel/sqlite) | +| Ma'lumotlar bazasi | Haydovchi | +| ------------------ | ------------------------------------------------------------------------------------ | +| PostgreSQL | [github.com/goravel/postgres](https://github.com/goravel/postgres) | +| MySQL | [github.com/goravel/mysql](https://github.com/goravel/mysql) | +| SQL Server | [github.com/goravel/sqlserver](https://github.com/goravel/sqlserver) | +| SQLite | [github.com/goravel/sqlite](https://github.com/goravel/sqlite) | -## Configuration +## Konfiguratsiya -The database configuration file is `config/database.go`. You can configure all database connections in this file and specify the default database connection. Most of the configuration in this file is based on the project's environment variables. +Ma'lumotlar bazasi konfiguratsiya fayli `config/database.go` faylidir. Siz ushbu faylda barcha ma'lumotlar bazasi ulanishlarini sozlashingiz va standart ma'lumotlar bazasi ulanishini belgilashingiz mumkin. Ushbu fayldagi konfiguratsiyaning aksariyati loyihaning muhit o'zgaruvchilari asosida qurilgan. -### Connection Pool +### Ulanish havzasi -You can configure the database connection pool in the configuration file to improve the concurrency performance by properly configuring the connection pool parameters: +Siz konfiguratsiya faylida ma'lumotlar bazasi ulanish havzasini sozlashingiz mumkin, bu esa ulanish havzasi parametrlarini to'g'ri sozlash orqali bir vaqtning o'zida ishlash samaradorligini oshirishga yordam beradi: -| Configuration Key | Description | -| -------------------------------------------------------------------------------- | ---------------------------- | -| pool.max_idle_conns | Maximum idle connections | -| pool.max_open_conns | Maximum connections | -| pool.conn_max_idletime | Connection maximum idle time | -| pool.conn_max_lifetime | Connection maximum lifetime | +| Konfiguratsiya kaliti | Tavsif | +| -------------------------------------------------------------------------------- | --------------------------------- | +| pool.max_idle_conns | Maksimal bo‘sh ulanishlar | +| pool.max_open_conns | Maksimal ulanishlar | +| pool.conn_max_idletime | Ulanishning maksimal ishsiz vaqti | +| pool.conn_max_lifetime | Ulanishning maksimal umri | -### Read-Write Splitting +### O‘qish-yozishni ajratish -Sometimes you may want to use a database connection to execute `SELECT` statements, while `INSERT`, `UPDATE`, and `DELETE` statements are executed by another database connection. In Goravel, it is easy to implement read-write splitting. +Ba'zan siz `SELECT` so'rovlarini bajarish uchun ma'lumotlar bazasi ulanishidan foydalanishingiz mumkin, shu bilan birga `INSERT`, `UPDATE` va `DELETE` so'rovlari boshqa ma'lumotlar bazasi ulanishi tomonidan bajarilishi mumkin. Goravelda o'qish-yozishni ajratishni amalga oshirish oson. ```go import "github.com/goravel/framework/contracts/database" @@ -55,15 +55,15 @@ import "github.com/goravel/framework/contracts/database" } ``` -We have added two keys, `read` and `write`, in the database configuration. `192.168.1.1` will be used as the "read" connection host, and `192.168.1.2` will be used as the "write" connection host. These two connections will share the configurations in the `mysql` array, such as the database prefix and character encoding. If there are multiple values in the `read` or `write` arrays, Goravel will randomly select the database host for each connection. +Biz ma'lumotlar bazasi konfiguratsiyasida `read` va `write` nomli ikkita kalit qo'shdik. `192.168.1.1` "o'qish" ulanishi uchun xost sifatida ishlatiladi, `192.168.1.2` esa "yozish" ulanishi uchun xost sifatida ishlatiladi. Bu ikki ulanish "mysql" massividagi ma'lumotlar bazasi prefiksi va belgilar kodlash kabi konfiguratsiyalarni baham ko'radi. Agar `read` yoki `write` massivlarida bir nechta qiymatlar bo'lsa, Goravel har bir ulanish uchun ma'lumotlar bazasi xostini tasodifiy tanlaydi. -## Running Native SQL Queries +## Asl SQL so'rovlarini ishga tushirish -After configuring the database connection, you can use `facades.DB()` to run queries. `facades.DB()` provides various methods for running queries: `Select`, `Insert`, `Update`, `Delete`, and `Statement`. +Ma'lumotlar bazasi ulanishini sozlashdan so'ng, so'rovlarni bajarish uchun `facades.DB()` dan foydalanishingiz mumkin. `facades.DB()` turli xil so'rovlarni bajarish uchun bir qancha usullarni taqdim etadi: `Select`, `Insert`, `Update`, `Delete` va `Statement`. -### Select +### Tanlash -Use the `facades.DB().Select()` method to execute basic queries: +Oddiy so'rovlarni bajarish uchun `facades.DB().Select()` usulidan foydalaning: ```go // Get multiple records @@ -75,55 +75,55 @@ var product Product err := facades.DB().Select(&product, "SELECT * FROM products WHERE id = ?", 1) ``` -> Note: Different database drivers require different placeholders. For example, the `?` placeholder is used for MySQL, while the `@` placeholder is used for PostgreSQL. +> Eslatma: Turli ma'lumotlar bazasi drayverlari turli joy egallovchilarni talab qiladi. Masalan, `?` belgisi MySQL uchun, `@` belgisi esa PostgreSQL uchun ishlatiladi. -### Insert +### Kiritish -Use the `facades.DB().Insert()` method to execute insertion statements: +"facades.DB().Insert()" usulidan foydalanib, kiritish bayonotlarini bajarish uchun: ```go result, err := facades.DB().Insert("insert into users (name, email) values (?, ?)", "Goravel", "goravel@example.com") ``` -### Update +### Yangilash -Use the `facades.DB().Update()` method to execute update statements: +Yangilash bayonotlarini bajarish uchun `facades.DB().Update()` usulidan foydalaning: ```go result, err := facades.DB().Update("update users set name = ? where id = ?", "Goravel", 1) ``` -### Delete +### O‘chirish -Use the `facades.DB().Delete()` method to execute delete statements: +O'chirish bayonotlarini bajarish uchun `facades.DB().Delete()` usulidan foydalaning: ```go result, err := facades.DB().Delete("delete from users where id = ?", 1) ``` -### Statement +### Bayonot -Use the `facades.DB().Statement()` method to execute general statements: +Umumiy bayonotlarni bajarish uchun `facades.DB().Statement()` usulidan foydalaning: ```go err := facades.DB().Statement("drop table users") ``` -### Using Multiple Database Connections +### Bir nechta ma'lumotlar bazasi ulanishlaridan foydalanish -If you define multiple database connections in the configuration file, you can specify the connection to use by calling the `facades.DB().Connection()` method: +Agar konfiguratsiya faylida bir nechta ma'lumotlar bazasi ulanishlarini belgilasangiz, `facades.DB().Connection()` usulini chaqirish orqali foydalaniladigan ulanishni ko'rsatishingiz mumkin: ```go var user User err := facades.DB().Connection("postgres").Select(&user, "select * from users where id = ?", 1) ``` -## Database Transactions +## Ma'lumotlar bazasi tranzaksiyalari -You can use the `facades.DB().Transaction()` method to execute a series of operations in a database transaction. If an exception is thrown in the transaction closure, the transaction will be automatically rolled back. If the closure executes successfully, the transaction will be automatically committed: +Siz ma'lumotlar bazasi transaksiyasida bir qator operatsiyalarni bajarish uchun `facades.DB().Transaction()` usulidan foydalanishingiz mumkin. Agar tranzaksiya yopilishida istisno yuzaga kelsa, tranzaksiya avtomatik ravishda orqaga qaytariladi. Agar yopilish muvaffaqiyatli bajarilsa, tranzaksiya avtomatik ravishda tasdiqlanadi: ```go -import "github.com/goravel/framework/contracts/database/db" +mport "github.com/goravel/framework/contracts/database/db" err := facades.DB().Transaction(func(tx db.Tx) error { _, err := tx.Table("products").Insert(Product{Name: "transaction product1"}) @@ -132,9 +132,9 @@ err := facades.DB().Transaction(func(tx db.Tx) error { }) ``` -### Manually Using Transactions +### Qo‘lda Tranzaksiyalardan Foydalanish -If you want to manually control the start, commit, and rollback of a transaction, you can use the `Begin`、`Commit` and `Rollback` methods: +Agar siz tranzaksiyaning boshlanishi, tasdiqlanishi va bekor qilinishini qo'lda boshqarishni istasangiz, `Begin`, `Commit` va `Rollback` metodlaridan foydalanishingiz mumkin: ```go tx, err := facades.DB().BeginTransaction() @@ -154,29 +154,29 @@ if err != nil { } ``` -## Checking Databases +## Ma'lumotlar bazalarini tekshirish -### Database Overview +### Ma'lumotlar bazasi haqida umumiy ma'lumot -Goravel provides several Artisan commands to help you understand the structure of the database. +Goravel ma'lumotlar bazasining tuzilishini tushunishga yordam beradigan bir nechta Artisan buyruqlarini taqdim etadi. -You can use the `db:show` command to view all tables in the database. +Siz ma'lumotlar bazasidagi barcha jadvallarni ko'rish uchun `db:show` buyrug'idan foydalanishingiz mumkin. ```bash ./artisan db:show ./artisan db:show --database=postgres ``` -You can also use the `db:table` command to view the structure of a specific table. +Shuningdek, siz ma'lum bir jadvalning tuzilishini ko'rish uchun `db:table` buyrug'idan foydalanishingiz mumkin. ```bash ./artisan db:table ./artisan db:table --database=postgres ``` -### Table Overview +### Jadvalga umumiy nazar -If you want to get an overview of a single table in the database, you can execute the `db:table` Artisan command. This command provides an overview of a database table, including its columns, types, attributes, keys, and indexes: +Agar ma'lumotlar bazasidagi bitta jadvalni umumiy ko'rinishini olishni istasangiz, `db:table` Artisan buyrug'ini bajarishingiz mumkin. Bu buyruq ma'lumotlar bazasi jadvalining umumiy ko'rinishini taqdim etadi, jumladan uning ustunlari, turlari, atributlari, kalitlari va indekslari: ```bash ./artisan db:table users From 70551112f32f95cc76002e2fefff0e84c4db7e1c Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Wed, 1 Apr 2026 16:18:00 +0800 Subject: [PATCH 085/163] New translations migrations.md (Uzbek) [skip ci] Update translations (Uzbek) migrations.md --- uz_UZ/database/migrations.md | 201 +++++++++++++++++------------------ 1 file changed, 100 insertions(+), 101 deletions(-) diff --git a/uz_UZ/database/migrations.md b/uz_UZ/database/migrations.md index d3d9a8969..f9e944146 100644 --- a/uz_UZ/database/migrations.md +++ b/uz_UZ/database/migrations.md @@ -1,40 +1,40 @@ -# Migrations +# Migratsiyalar [[toc]] -## Introduction +## Kirish -When multiple people collaborate to develop applications, it's crucial to have a standardized database structure for synchronization. Without this, there could be chaos as everyone's individual data won't match up. Database migration is the solution to this problem. The database structure is version-controlled to ensure its consistency within all developers. +Bir necha odam ilovalarni ishlab chiqishda hamkorlik qilganda, sinxronizatsiya uchun standartlashtirilgan ma'lumotlar bazasi tuzilishiga ega bo'lish juda muhimdir. Bunisiz, har bir kishining individual ma'lumotlari mos kelmasligi sababli tartibsizlik yuzaga kelishi mumkin. Ma'lumotlar bazasi migratsiyasi bu muammoning yechimidir. Ma'lumotlar bazasi tuzilishi versiyalarni boshqarish orqali barcha ishlab chiquvchilar orasida uning izchilligini ta'minlash uchun nazorat qilinadi. -## Configuration +## Konfiguratsiya -The database migration files are stored in the `database/migrations` directory. You can configure the database connection information in the `config/database.go` file. +Ma'lumotlar bazasi migratsiya fayllari `database/migrations` katalogida saqlanadi. Siz `config/database.go` faylida ma'lumotlar bazasi ulanish ma'lumotlarini sozlashingiz mumkin. ```go -"migrations": map[string]any{ - // You can cumstomize the table name of migrations - "table": "migrations", -}, +"migratsiyalar": map[string]any{ + // Siz migratsiyalar jadvalining nomini o'zgartirishingiz mumkin + "table": "migratsiyalar", +} ``` -## Create Migrations +## Migratsiyalarni yaratish -Use the `make:migration` command to create the migration: +Migratsiyani yaratish uchun `make:migration` buyrug'idan foydalaning: ```shell ./artisan make:migration ./artisan make:migration create_users_table ``` -This command will generate migration files in the `database/migrations` directory. Each migration file will begin with a timestamp, which Goravel will use to determine the execution order of the migration files. +Bu buyruq `database/migrations` katalogida migratsiya fayllarini yaratadi. Har bir migratsiya fayli vaqt belgisi bilan boshlanadi, Goravel migratsiya fayllarini bajarish tartibini aniqlash uchun undan foydalanadi. -You can also create a migration for a specific model by using the `-m` or `--model` option: +Shuningdek, siz `-m` yoki `--model` opsiyasidan foydalanib, ma'lum bir model uchun migratsiya yaratishingiz mumkin: ```shell ./artisan make:migration create_users_table -m User ``` -The model should be registered in the `bootstrap/app.go` file before running the command. This command will generate a migration file based on the structure defined in the `User` model. +Model buyrug'ni ishga tushirishdan oldin `bootstrap/app.go` faylida ro'yxatdan o'tkazilishi kerak. Bu buyruq `User` modelida belgilangan tuzilish asosida migratsiya faylini yaratadi. ```go func Boot() contractsfoundation.Application { @@ -49,32 +49,32 @@ func Boot() contractsfoundation.Application { } ``` -### Quickly Create +### Tez yaratish -Use `create_users_table` to automatically generate a table containing the infrastructure of `users`: +`create_users_table` dan foydalanib, `users` jadvalining infratuzilmasini o'z ichiga olgan jadvalni avtomatik yarating: ``` ^create_(\w+)_table$ ^create_(\w+)$ ``` -Use `add_avatar_to_users_table` to automatically generate a structure for adding fields to the `users` table: +`users` jadvaliga maydonlar qo'shish uchun tuzilmani avtomatik yaratish uchun `add_avatar_to_users_table` dan foydalaning: ``` _(to|from|in)_(\w+)_table$ _(to|from|in)_(\w+)$ ``` -If the above conditions are not matched, the framework will generate an empty migration file. +Yuqoridagi shartlar bajarilmagan taqdirda, framework bo‘sh migratsiya faylini yaratadi. -## Migration Structure +## Migratsiya tuzilmasi -### Go Language Migration +### Go Tili Migratsiyasi -The migration struct contains two methods: `Up` and `Down`. The `Up` method is used to add new tables, columns, or indexes to the database, while the `Down` method is used to undo the operations performed by the `Up` method. In these two methods, you can use `facades.Schema()` to create and operate database tables. For available methods, see the [documentation](#tables). The following migration will create a `users` table: +Migratsiya strukturasida ikkita metod mavjud: `Up` va `Down`. `Up` usuli ma'lumotlar bazasiga yangi jadvallar, ustunlar yoki indekslar qo'shish uchun ishlatiladi, `Down` usuli esa `Up` usuli tomonidan bajarilgan amallarni bekor qilish uchun ishlatiladi. Ushbu ikki usulda siz `facades.Schema()` yordamida ma'lumotlar bazasi jadvallarini yaratish va boshqarish mumkin. Mavjud usullar uchun [hujjat](#tables)ga qarang. Quyidagi migratsiya `users` jadvalini yaratadi: ```go -package migrations +migratsiyalar paketi import ( "github.com/goravel/framework/contracts/database/schema" @@ -85,12 +85,12 @@ import ( type M20241207095921CreateUsersTable struct { } -// Signature The unique signature for the migration. +// Imzo Migratsiyaning noyob imzosi. func (r *M20241207095921CreateUsersTable) Signature() string { return "20241207095921_create_users_table" } -// Up Run the migrations. +// Yuqoriga Migratsiyalarni ishga tushiring. func (r *M20241207095921CreateUsersTable) Up() error { if !facades.Schema().HasTable("users") { return facades.Schema().Create("users", func(table schema.Blueprint) { @@ -104,15 +104,15 @@ func (r *M20241207095921CreateUsersTable) Up() error { return nil } -// Down Reverse the migrations. +// Pastga Migratsiyalarni teskari aylantiring. func (r *M20241207095921CreateUsersTable) Down() error { return facades.Schema().DropIfExists("users") } ``` -#### Set Migration Connection +#### Migratsiya ulanishini o'rnatish -If the migration will interact with a database connection other than the application's default database connection, you should use the migration's `Connection` method: +Agar migratsiya ilovaning standart ma'lumotlar bazasi ulanishidan boshqa ma'lumotlar bazasi ulanishi bilan o'zaro ta'sirlashsa, siz migratsiyaning `Connection` metodidan foydalanishingiz kerak: ```go func (r *M20241207095921CreateUsersTable) Connection() string { @@ -120,9 +120,9 @@ func (r *M20241207095921CreateUsersTable) Connection() string { } ``` -## Register Migrations +## Migratsiyalarni ro'yxatdan o'tkazish -A new migration created by `make:migration` will be registered automatically in the `bootstrap/migrations.go::Migrations()` function and the function will be called by `WithMigrations`. You need register the rule manually if you create the migration file by yourself. +`make:migration` tomonidan yaratilgan yangi migratsiya `bootstrap/migrations.go::Migrations()` funksiyasida avtomatik ravishda ro'yxatga olinadi va funksiya `WithMigrations` tomonidan chaqiriladi. Agar siz migratsiya faylini o'zingiz yaratsangiz, qoidani qo'lda ro'yxatdan o'tkazishingiz kerak. ```go func Boot() contractsfoundation.Application { @@ -133,71 +133,71 @@ func Boot() contractsfoundation.Application { } ``` -## Run Migrations +## Migratsiyalarni ishga tushirish -To run all of your outstanding migrations, execute the `migrate` Artisan command: +Barcha qoldirilgan migratsiyalaringizni ishga tushirish uchun `migrate` Artisan buyrug'ini bajaring: ```shell ./artisan migrate ``` -If you would like to see which migrations have run thus far, you may use the `migrate:status` Artisan command: +Agar hozirgacha qaysi migratsiyalar ishlaganini ko'rmoqchi bo'lsangiz, `migrate:status` Artisan buyrug'idan foydalanishingiz mumkin: ```shell ./artisan migrate:status ``` -## Rolling Back Migrations +## Migratsiyalarni Orqaga Qaytarish -To roll back the latest migration batch, use the `rollback` Artisan command: +Oxirgi migratsiya to'plamini orqaga qaytarish uchun `rollback` Artisan buyrug'idan foydalaning: ```shell ./artisan migrate:rollback ``` -If you want to roll back multiple migration batches, you can specify the `batch` option, the number indicates which batch to roll back: +Agar siz bir nechta migratsiya to'plamlarini orqaga qaytarmoqchi bo'lsangiz, `batch` opsiyasini belgilashingiz mumkin, raqam qaysi to'plamni orqaga qaytarish kerakligini ko'rsatadi: ```shell ./artisan migrate:rollback --batch=2 ``` -You may roll back a limited number of migrations by providing the `step` option to the `rollback` command. For example, the following command will roll back the last five migrations: +Siz `rollback` buyrug'iga `step` opsiyasini berib, cheklangan migratsiyalarni qaytarishingiz mumkin. Masalan, quyidagi buyruq oxirgi beshta migratsiyani orqaga qaytaradi: ```shell ./artisan migrate:rollback --step=5 ``` -The `migrate:reset` command will roll back all of your application's migrations: +`migrate:reset` buyrug'u ilovangizning barcha migratsiyalarini orqaga qaytaradi: ```shell ./artisan migrate:reset ``` -### Roll Back & Migrate Using A Single Command +### Bitta buyruq yordamida orqaga qaytarish va migratsiya qilish -The `migrate:refresh` command will roll back all of your migrations and then execute the `migrate` command. This command effectively re-creates your entire database: +`migrate:refresh` buyrug'i barcha migratsiyalaringizni orqaga qaytaradi va keyin `migrate` buyrug'ini bajaradi. Bu buyruq sizning butun ma'lumotlar bazangizni samarali ravishda qayta yaratadi: ```shell ./artisan migrate:refresh ``` -You may roll back and re-migrate a limited number of migrations by providing the `step` option to the `refresh` command. For example, the following command will roll back and re-migrate the last five migrations: +Siz `refresh` buyrug'iga `step` opsiyasini berib, cheklangan migratsiyalarni orqaga qaytarish va qayta migratsiya qilishingiz mumkin. Masalan, quyidagi buyruq oxirgi besh migratsiyani orqaga qaytaradi va qayta migratsiya qiladi: ```shell ./artisan migrate:refresh --step=5 ``` -### Drop All Tables & Migrate +### Barcha Jadval va Migratsiyalarni O'chirish -The `migrate:fresh` command will drop all tables from the database and then execute the `migrate` command: +`migrate:fresh` buyrug'i ma'lumotlar bazasidagi barcha jadvallarni o'chirib tashlaydi va keyin `migrate` buyrug'ini bajaradi: ```shell ./artisan migrate:fresh ``` -## Tables +## Jadvallar -### Create Table +### Jadval yaratish ```go facades.Schema().Create("users", func(table schema.Blueprint) { @@ -208,7 +208,7 @@ facades.Schema().Create("users", func(table schema.Blueprint) { }) ``` -### Check If Table / Column Exists +### Jadval / Ustun Mavjudligini Tekshirish ```go if facades.Schema().HasTable("users") {} @@ -217,7 +217,7 @@ if facades.Schema().HasColumns("users", []string{"name", "email"}) {} if facades.Schema().HasIndex("users", "email_unique") {} ``` -### Database Connection +### Ma'lumotlar bazasi ulanishi ```go facades.Schema().Connection("sqlite").Create("users", func(table schema.Blueprint) { @@ -225,7 +225,7 @@ facades.Schema().Connection("sqlite").Create("users", func(table schema.Blueprin }) ``` -### Update Table +### Jadvalni yangilash ```go facades.Schema().Table("users", func(table schema.Blueprint) { @@ -233,7 +233,7 @@ facades.Schema().Table("users", func(table schema.Blueprint) { }) ``` -### Rename Column +### Ustun nomini o'zgartirish ```go facades.Schema().Table("users", func(table schema.Blueprint) { @@ -241,7 +241,7 @@ facades.Schema().Table("users", func(table schema.Blueprint) { }) ``` -### Add Table Comment +### Jadval izohini qo'shish ```go facades.Schema().Table("users", func(table schema.Blueprint) { @@ -249,76 +249,75 @@ facades.Schema().Table("users", func(table schema.Blueprint) { }) ``` -### Rename / Drop Table +### Jadvalni qayta nomlash / O‘chirish ```go facades.Schema().Rename("users", "new_users") facades.Schema().Drop("users") facades.Schema().DropIfExists("users") - ``` -## Columns +## Ustunlar -### Available Column Types +### Mavjud ustun turlari -#### Boolean Types +#### Mantiqiy turlar -Boolean +Mantiqiy -#### String & Text Types +#### Satr va matn turlari Char, Json, LongText, MediumText, String, Text, LongText, TinyText, Uuid, Ulid -#### Numeric Types +#### Raqamli turlar BigIncrements, BigInteger, Decimal, Double, Float, [ID](#id), Increments, Integer, IntegerIncrements, MediumIncrements, MediumInteger, SmallIncrements, SmallInteger, TinyIncrements, TinyInteger, UnsignedBigInteger, UnsignedInteger, UnsignedMediumInteger, UnsignedSmallInteger, UnsignedTinyInteger -#### Date & Time Types +#### Sana va Vaqt Turlari -Date, DateTime, DateTimeTz, [SoftDeletes](#softdeletes), SoftDeletesTz, Time, TimeTz, Timestamp, TimestampTz, Timestamps, TimestampsTz +Sana, SanaVaqt, SanaVaqtTz, [YumshoqO'chirishlar](#softdeletes), YumshoqO'chirishlarTz, Vaqt, VaqtTz, VaqtBelgisi, VaqtBelgisiTz, VaqtBelgilari, VaqtBelgilariTz -#### Other Types +#### Boshqa turlar -[Enum](#enum), Morphs, NullableMorphs, NumericMorphs, UuidMorphs, UlidMorphs +[Enum](#enum), Morflar, NullableMorflar, NumericMorflar, UuidMorflar, UlidMorflar #### Enum -Create an `Enum` field that can be stored in `Mysql` according to the type in `[]any`, but in `Postgres`, `Sqlite`, and `Sqlserver` databases, it is a `String` type. +`[]any` turidagi bo‘yicha `Mysql` da saqlanishi mumkin bo‘lgan `Enum` maydonini yarating, lekin `Postgres`, `Sqlite` va `Sqlserver` ma’lumotlar bazalarida u `String` turidir. ```go -table.Enum("difficulty", []any{"easy", "hard"}) -table.Enum("num", []any{1, 2}) +table.Enum("qiyinlik", []any{"oson", "qiyin"}) +table.Enum("raqam", []any{1, 2}) ``` #### ID -The `ID` method is an alias for the `BigIncrements` method. By default, this method will create an `id` column; however, if you would like to assign a different name to the column, you may pass the column name: +`ID` usuli `BigIncrements` usulining taxallusidir. Standart holda, ushbu usul `id` ustunini yaratadi; ammo, agar siz ustunga boshqa nom berishni istasangiz, ustun nomini o'tkazishingiz mumkin: ```go -table.ID() -table.ID("user_id") +jadval.ID() +jadval.ID("foydalanuvchi_id") ``` -#### SoftDeletes +#### Yumşoq o'chirishlar -The `SoftDeletes` method adds a nullable `deleted_at` `TIMESTAMP` column. This column is intended to store the `deleted_at` timestamp required for the Orm "soft delete" feature: +`SoftDeletes` usuli `deleted_at` `TIMESTAMP` ustunini qo‘shadi. Bu ustun Orm "yumshoq o'chirish" funksiyasi uchun zarur bo'lgan `deleted_at` vaqt belgisini saqlash uchun mo'ljallangan: ```go table.SoftDeletes() ``` -#### Custom column +#### Maxsus ustun -If you are using column types that framework does not support yet, you can use the `Column` method to customize the field type: +Agar siz freymvork hali qo'llab-quvvatlamaydigan ustun turlaridan foydalanayotgan bo'lsangiz, maydon turini sozlash uchun `Column` metodidan foydalanishingiz mumkin: ```go -table.Column("geometry", "geometry") +table.Column("geometriya", "geometriya") ``` -### Column Modifiers +### Ustun modifikatorlari -In addition to the column types listed above, when adding a column to a database table, you can also add "modifiers" to the column. For example, to allow a column to be "nullable," you can use the `Nullable` method: +Yuqorida keltirilgan ustun turlaridan tashqari, ma'lumotlar bazasi jadvaliga ustun qo'shganda, siz shuningdek, ustunga "modifikatorlar" qo'shishingiz mumkin. Masalan, ustunni "null qiymat qabul qiluvchi" qilish uchun `Nullable` metodidan foydalanishingiz mumkin: ```go facades.Schema().Table("users", func(table schema.Blueprint) { @@ -326,24 +325,24 @@ facades.Schema().Table("users", func(table schema.Blueprint) { }) ``` -The following table contains all available column modifiers: +Quyidagi jadvalda barcha mavjud ustun modifikatorlari keltirilgan: -| Modified | Description | -| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `.Always()` | The value of this column is always generated by the database system, and users cannot directly insert or modify it (only PostgreSQL) | -| `.AutoIncrement()` | Sets an integer column as auto-incrementing (primary key) | -| `.After("column")` | Sets the column after the specified column (MySQL only) | -| `.Comment("my comment")` | Adds a comment to the column (MySQL / PostgreSQL) | -| `.Change()` | Modify the column structure (MySQL / PostgreSQL / Sqlserver) | -| `.Default(value)` | Sets the default value for the column | -| `.First()` | Sets the column as the first column (MySQL only) | -| `.GeneratedAs()` | Sets the value of the column to be generated by the database system (only PostgreSQL) | -| `.Nullable()` | Allows NULL values to be inserted into the column | -| `.Unsigned()` | Sets an integer column as UNSIGNED (MySQL only) | -| `.UseCurrent()` | Sets a timestamp column to use CURRENT_TIMESTAMP as the default value | -| `.UseCurrentOnUpdate()` | Sets a timestamp column to use CURRENT_TIMESTAMP when the record is updated (MySQL only) | +| O'zgartirilgan | Tavsif | +| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `.Har doim()` | Ushbu ustunning qiymati har doim ma'lumotlar bazasi tizimi tomonidan yaratiladi va foydalanuvchilar uni to'g'ridan-to'g'ri kiritish yoki o'zgartirishlari mumkin emas (faqat PostgreSQL) | +| `.AutoIncrement()` | Butun sonli ustunni avtomatik o'sish (asosiy kalit) sifatida belgilaydi | +| `.After("ustun")` | Belgilangan ustundan keyingi ustunni o‘rnatadi (faqat MySQL) | +| `.Comment("mening izohim")` | Ustunga izoh qo'shadi (MySQL / PostgreSQL) | +| \`.Change() | Ustun tuzilishini o'zgartirish (MySQL / PostgreSQL / Sqlserver) | +| `.Default(value)` | Ustunning standart qiymatini belgilaydi | +| `.First()` | Ustunni birinchi ustun sifatida belgilaydi (faqat MySQL) | +| `.GeneratedAs()` | Ushbu ustunning qiymatini ma'lumotlar bazasi tizimi tomonidan yaratilishi uchun belgilaydi (faqat PostgreSQL) | +| `.Nullable()` | Ustunga NULL qiymatlarni kiritishga ruxsat beradi | +| `.Unsigned()` | Butun sonli ustunni UNSIGNED qilib belgilaydi (faqat MySQL uchun) | +| `.UseCurrent()` | Jadval ustuniga standart qiymat sifatida CURRENT_TIMESTAMP ni belgilaydi | +| `.UseCurrentOnUpdate()` | Yozuv yangilanganda CURRENT_TIMESTAMP dan foydalanish uchun vaqt belgisi ustunini belgilaydi (faqat MySQL) | -### Drop Column +### Ustunni tashlash ```go facades.Schema().Table("users", func(table schema.Blueprint) { @@ -352,32 +351,32 @@ facades.Schema().Table("users", func(table schema.Blueprint) { }) ``` -## Indexes +## Indekslar -### Create Index +### Indeks yaratish ```go facades.Schema().Table("users", func(table schema.Blueprint) { - // Add primary key + // Asosiy kalitni qo'shish table.Primary("id") - // Add composite primary key + // Kompozit asosiy kalitni qo'shish table.Primary("id", "name") - // Add unique index + // Yagona indeksni qo'shish table.Unique("name") table.Unique("name", "age") - // Add normal index + // Oddiy indeksni qo'shish table.Index("name") table.Index("name", "age") - // Add fulltext index + // To'liq matn indeksini qo'shish table.FullText("name") table.FullText("name", "age") }) ``` -### Rename Index +### Indeksni nomini o'zgartirish ```go facades.Schema().Table("users", func(table schema.Blueprint) { @@ -385,7 +384,7 @@ facades.Schema().Table("users", func(table schema.Blueprint) { }) ``` -### Drop Index +### Indeksni tashlash ```go facades.Schema().Table("users", func(table schema.Blueprint) { @@ -399,7 +398,7 @@ facades.Schema().Table("users", func(table schema.Blueprint) { }) ``` -### Create Foreign Key +### Tashqi kalit yaratish ```go facades.Schema().Table("posts", func(table schema.Blueprint) { @@ -408,7 +407,7 @@ facades.Schema().Table("posts", func(table schema.Blueprint) { }) ``` -### Drop Foreign Key +### Tashqi kalitni olib tashlash ```go facades.Schema().Table("users", func(table schema.Blueprint) { From 0213ce98533a1150e9cce4ee0a436b7b6faf5fac Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Wed, 1 Apr 2026 18:53:03 +0800 Subject: [PATCH 086/163] New translations queries.md (Uzbek) [skip ci] Update translations (Uzbek) queries.md --- uz_UZ/database/queries.md | 226 +++++++++++++++++++------------------- 1 file changed, 113 insertions(+), 113 deletions(-) diff --git a/uz_UZ/database/queries.md b/uz_UZ/database/queries.md index 87343a12b..41ff4acb8 100644 --- a/uz_UZ/database/queries.md +++ b/uz_UZ/database/queries.md @@ -1,16 +1,16 @@ -# Query Builder +# So'rov Quruvchi [[toc]] -## Introduction +## Kirish -The database query builder provides a convenient interface to create and execute database queries. It can be used to perform most database operations in your application and works with all supported database systems. +Ma'lumotlar bazasi so'rovlari quruvchisi ma'lumotlar bazasi so'rovlarini yaratish va bajarish uchun qulay interfeysni taqdim etadi. U ilovangizda ko'p ma'lumotlar bazasi operatsiyalarini bajarish uchun ishlatilishi mumkin va barcha qo'llab-quvvatlanadigan ma'lumotlar bazasi tizimlari bilan ishlaydi. -Query builder uses parameter binding to protect your application from SQL injection. You don't need to clean or escape strings passed to the query builder. +So'rov quruvchisi SQL in'ektsiyasidan himoya qilish uchun parametr bog'lashdan foydalanadi. So'rov quruvchisiga uzatilgan satrlarni tozalash yoki qochishga hojat yo'q. -## Running Queries +## So'rovlarni bajarish -Framework provides various query methods, you can query, create, update and delete data in the database. Note that when you want to bind data to `struct` or [model](../orm/getting-started.md#model-definition), you need to add the `db` tag to the field: +Framework turli xil so'rov usullarini taqdim etadi, siz ma'lumotlar bazasidan ma'lumotlarni so'rashingiz, yaratishingiz, yangilashingiz va o'chirishingiz mumkin. E'tibor bering, ma'lumotlarni `struct` yoki [model](../orm/getting-started.md#model-definition) ga bog'lamoqchi bo'lganingizda, maydonga `db` tegnini qo'shishingiz kerak: ```go type User struct { @@ -25,54 +25,54 @@ type User struct { } ``` -### Retrieving All Rows +### Barcha qatorlarni olish -You can use the `facades.DB()` provided `table` method to start a query. The `table` method returns a chainable query builder instance for the specified table, allowing you to chain more constraints, and finally use the `Get` method to retrieve the query results: +Siz so'rovni boshlash uchun `facades.DB()` tomonidan taqdim etilgan `table` usulidan foydalanishingiz mumkin. `table` usuli belgilangan jadval uchun zanjirli so'rov quruvchi namunasini qaytaradi, bu sizga qo'shimcha cheklovlarni zanjirlash va natijalarni olish uchun `Get` usulidan foydalanish imkonini beradi: ```go var users []User err := facades.DB().Table("users").Get(&users) ``` -### Retrieving a Single Row or Column +### Bitta qator yoki ustunni olish -If you only need to retrieve a single row of data from the database table, you can use the `First` method. +Agar sizga ma'lumotlar bazasi jadvalidan faqat bitta qator ma'lumotlarni olish kerak bo'lsa, siz "First" usulidan foydalanishingiz mumkin. ```go var user User err := facades.DB().Table("users").Where("id", 1).First(&user) ``` -You can use the `Value` method to retrieve the value of a single column: +Bitta ustunning qiymatini olish uchun `Value` usulidan foydalanishingiz mumkin: ```go var name string err := facades.DB().Table("users").Where("id", 1).Value("name", &name) ``` -You can use the `Find` method to retrieve a single row of data by passing the `id`: +Siz `id` ni o'tkazish orqali ma'lumotlarning bitta qatorini olish uchun `Find` usulidan foydalanishingiz mumkin: ```go var user User err := facades.DB().Table("users").Find(&user, 1) -// You can also pass a collection of `id` to retrieve multiple rows of data +// Shuningdek, bir nechta ma'lumot qatorlarini olish uchun id to'plamini o'tkazishingiz mumkin var users []User err := facades.DB().Table("users").Find(&users, []int{1, 2, 3}) -// Find defaults the table primary key to `id`, if the table primary key is not `id`, you can pass the `id` field name +// Find jadvalning asosiy kalitini sukut bo'yicha id deb belgilaydi, agar jadvalning asosiy kaliti id bo'lmasa, id maydon nomini o'tkazishingiz mumkin var user User err := facades.DB().Table("users").Find(&users, "uuid", "1") ``` -You can use the `FindOrFail` or `FirstOrFail` method, if the record is not found, it will throw a `sql.ErrNoRows` error: +Agar yozuv topilmasa, `FindOrFail` yoki `FirstOrFail` usulidan foydalanishingiz mumkin, u `sql.ErrNoRows` xatosini chiqaradi: ```go var user User err := facades.DB().Table("users").FindOrFail(&user, 1) ``` -You can use the `FindOr` or `FirstOr` method, if the record is not found, it will execute the closure function: +Agar yozuv topilmasa, `FindOr` yoki `FirstOr` usulidan foydalanishingiz mumkin, u holda yopish funksiyasi bajariladi: ```go var user *User @@ -81,18 +81,18 @@ err = facades.DB().Table("users").Where("name", "John").FirstOr(&user, func() er }) ``` -### Retrieving a Single Column Value +### Bitta ustun qiymatini olish -If you want to retrieve a list of records containing a single column value, you can use the `Pluck` method: +Agar siz bitta ustun qiymatini o'z ichiga olgan yozuvlar ro'yxatini olishni istasangiz, `Pluck` usulidan foydalanishingiz mumkin: ```go var emails []string err := facades.DB().Table("users").Pluck("email", &emails) ``` -### Traversing Results +### Natijalarni o'tish -You can use the `Each` method to traverse all results: +Siz `Each` metodidan barcha natijalarni aylanib o'tish uchun foydalanishingiz mumkin: ```go var products []Product @@ -110,9 +110,9 @@ err := facades.DB().Table("products").Each(func(rows []db.Row) error { }) ``` -### Chunking Results +### Chunking natijalari -If you need to process thousands of database records, consider using the `Chunk` method. This method retrieves a small chunk of results at a time and passes each chunk to a closure function for processing: +Agar siz minglab ma'lumotlar bazasi yozuvlarini qayta ishlashingiz kerak bo'lsa, `Chunk` usulidan foydalanishni ko'rib chiqing. Bu usul natijalarni bir vaqtning o'zida kichik qismlarga ajratadi va har bir qismni qayta ishlash uchun yopilish funksiyasiga uzatadi: ```go var products []Product @@ -130,11 +130,11 @@ err := facades.DB().Table("products").Chunk(2, func(rows []db.Row) error { }) ``` -> Note: When modifying records in the Chunk callback, it may result in records not being included in the chunked results. +> Eslatma: Chunk chaqiruvida yozuvlarni o'zgartirish, yozuvlarning chunk natijalariga kiritilmasligiga olib kelishi mumkin. -### Cursor +### Kursor -A cursor can be used to process large amounts of data without loading all data into memory at once. It processes data one by one instead of loading all data at once. +Kursor barcha ma'lumotlarni bir vaqtning o'zida xotiraga yuklamasdan, katta hajmdagi ma'lumotlarni qayta ishlash uchun ishlatilishi mumkin. U barcha ma'lumotlarni bir vaqtning o'zida yuklash o'rniga, ma'lumotlarni birma-bir qayta ishlaydi. ```go rows, err := facades.DB().Table("products").Cursor() @@ -150,9 +150,9 @@ for row := range rows { } ``` -### Aggregates +### Agregatlar -The query builder provides aggregate methods: `Count`, `Sum`, `Avg`, `Min`, `Max`. +So'rov quruvchisi quyidagi yig'ish usullarini taqdim etadi: `Count`, `Sum`, `Avg`, `Min`, `Max`. ```go count, err := facades.DB().Table("users").Count() @@ -170,9 +170,9 @@ var max int err := facades.DB().Table("users").Max("age", &max) ``` -### Checking if a Record Exists +### Yozuv mavjudligini tekshirish -You can use the `Exists` and `DoesntExist` methods to determine if the result of a query condition exists: +Siz so'rov shartining natijasi mavjudligini aniqlash uchun `Exists` va `DoesntExist` metodlaridan foydalanishingiz mumkin: ```go exists, err := facades.DB().Table("users").Where("votes > ?", 100).Exists() @@ -180,9 +180,9 @@ exists, err := facades.DB().Table("users").Where("votes > ?", 100).Exists() exists, err := facades.DB().Table("users").Where("votes > ?", 100).DoesntExist() ``` -### Pagination +### Sahifalash -You can use the `Paginate` method to paginate the query results: +So'rov natijalarini sahifalash uchun `Paginate` metodidan foydalanishingiz mumkin: ```go var ( @@ -193,60 +193,60 @@ var ( err := facades.DB().Table("users").Where("name", "John").Paginate(1, 10, &users, &total) ``` -## Select +## Tanlash -You may not always want to retrieve all columns from a database table. Use the `Select` method to customize a "select" query statement to query the specified fields: +Siz har doim ma'lumotlar bazasi jadvalidan barcha ustunlarni olishni xohlamasligingiz mumkin. "Select" so'rov bayonini sozlash uchun `Select` usulidan foydalaning va belgilangan maydonlarni so'rang: ```go var users []User err := facades.DB().Table("users").Select("name", "email as user_email").Get(&users) ``` -The `Distinct` method will force the query to return unique results: +`Distinct` usuli so'rovning noyob natijalarni qaytarishini majbur qiladi: ```go var users []User err := facades.DB().Table("users").Distinct().Select("name").Get(&users) ``` -## Raw Expressions +## Xom ifodalar -Sometimes you may need to use raw expressions in your queries. You can use the `db.Raw` method to create a raw expression: +Ba'zan so'rovlaringizda to'g'ridan-to'g'ri ifodalardan foydalanish kerak bo'lishi mumkin. Siz `db.Raw` usulidan foydalanib, xom ifoda yaratishingiz mumkin: ```go -import "github.com/goravel/framework/database/db" +mport "github.com/goravel/framework/database/db" res, err := facades.DB().Model(&user).Update("age", db.Raw("age - ?", 1)) ``` -## Select +## Tanlash -### Specifying a Select Clause +### Select bandini belgilash -Of course, you may not always want to retrieve all columns from a database table. Use the `Select` method to specify a custom select clause for your query: +Albatta, siz har doim ma'lumotlar bazasi jadvalidan barcha ustunlarni olishni xohlamasligingiz mumkin. So'rovingiz uchun maxsus tanlash bandini belgilash uchun `Select` usulidan foydalaning: ```go -// Select specific fields +// Belgilangan maydonlarni tanlash err := facades.DB().Select("name", "age").Get(&users) -// Use a subquery +// Subquery-dan foydalanish err := facades.DB().Select("name", db.Raw("(SELECT COUNT(*) FROM posts WHERE users.id = posts.user_id) as post_count")).Get(&users) ``` -### Distinct +### Farqli -The `Distinct` method will force the query to return unique results: +`Distinct` usuli so'rovga noyob natijalarni qaytarishni majbur qiladi: ```go var users []models.User err := facades.DB().Distinct("name").Find(&users) ``` -## Raw Methods +## Xom usullar ### WhereRaw / OrWhereRaw -The `WhereRaw` and `OrWhereRaw` methods can be used to inject raw "where" clauses into your query. These methods accept an optional binding array as their second parameter: +`WhereRaw` va `OrWhereRaw` metodlari so'rovga "where" bandlarini bevosita kiritish uchun ishlatilishi mumkin. Ushbu usullar ikkinchi parametr sifatida ixtiyoriy bog'lash massivini qabul qiladi: ```go var users []User @@ -258,7 +258,7 @@ err := facades.DB().OrWhereRaw("age = ? or age = ?", []any{25, 30}).Get(&users) ### OrderByRaw -The `OrderByRaw` method can be used to set a raw string as the value of the "order by" clause: +`OrderByRaw` usuli "order by" bandining qiymati sifatida xom satrni o'rnatish uchun ishlatilishi mumkin: ```go var users []User @@ -266,11 +266,11 @@ var users []User err := facades.DB().OrderByRaw("age DESC, id ASC").Get(&users) ``` -## Joins +## Qo'shiladi -### Inner Join +### Ichki qo'shilish -The query builder can be used to write join statements. To execute a basic SQL "inner join", you can use the `Join` method on the query builder instance: +So'rov qurilgichini birlashtirish bayonotlarini yozish uchun ishlatish mumkin. "Ichki join" SQL so‘rovini bajarish uchun so‘rov quruvchi namunasidagi `Join` metodidan foydalanishingiz mumkin: ```go var users []User @@ -278,9 +278,9 @@ var users []User err := facades.DB().Table("users").Join("posts as p ON users.id = p.user_id AND p.id = ?", 1).Where("age", 25).Get(&users) ``` -### Left Join / Right Join +### Chap Join / O'ng Join -If you want to execute a "left join" or "right join", you can use the `LeftJoin` or `RightJoin` methods: +Agar siz "chap qo'shilish" yoki "o'ng qo'shilish"ni bajarishni istasangiz, `LeftJoin` yoki `RightJoin` usullaridan foydalanishingiz mumkin: ```go var users []User @@ -292,7 +292,7 @@ err = facades.DB().Table("users").RightJoin("posts as p ON users.id = p.user_id ### Cross Join -The `CrossJoin` method can be used to execute a "cross join": +`CrossJoin` usuli "cross join"ni bajarish uchun ishlatilishi mumkin: ```go var users []User @@ -300,11 +300,11 @@ var users []User err := facades.DB().Table("users").CrossJoin("posts as p ON users.id = p.user_id AND p.id = ?", 1).Where("age", 25).Get(&users) ``` -## Basic Where Clauses +## Asosiy Where Shartlari -### Where / OrWhere +### Qayerda / Yoki Qayerda -You can use the `Where` method on the query builder instance to add where clauses to the query. +Siz so'rov quruvchi namunasi ustida `Where` usulidan foydalanib, so'rovga where bandlarini qo'shishingiz mumkin. ```go import "github.com/goravel/framework/contracts/database/db" @@ -326,7 +326,7 @@ err := facades.DB().Where(func(query db.Query) db.Query { ### WhereNot / OrWhereNot -The `WhereNot` and `OrWhereNot` methods can be used to negate a given set of query conditions. +`WhereNot` va `OrWhereNot` metodlari berilgan so'rov shartlar to'plamini inkor qilish uchun ishlatilishi mumkin. ```go import "github.com/goravel/framework/contracts/database/db" @@ -346,9 +346,9 @@ err := facades.DB().WhereNot(func(query db.Query) db.Query { }).OrWhereNot("name", "John").Get(&users) ``` -### WhereExists / WhereNotExists +### Mavjud bo‘lgan joy / Mavjud bo‘lmagan joy -The `WhereExists` method allows you to write exists SQL clauses: +`WhereExists` usuli sizga mavjud SQL bandlarini yozish imkonini beradi: ```go var users []User @@ -374,11 +374,11 @@ facades.DB().Table("products").WhereNone([]string{"age", "score"}, ">", 18).Find // SQL: SELECT * FROM products WHERE NOT (age > ?) AND NOT (score > ?) ``` -### Other Where Clauses +### Boshqa Where bandlari **WhereBetween / OrWhereBetween** -The `WhereBetween` method verifies that a field value is between two given values: +`WhereBetween` usuli maydon qiymati berilgan ikki qiymat orasida ekanligini tekshiradi: ```go facades.DB().Table("users").WhereBetween("votes", 1, 100) @@ -386,7 +386,7 @@ facades.DB().Table("users").WhereBetween("votes", 1, 100) **WhereNotBetween / OrWhereNotBetween** -The `WhereNotBetween` method verifies that a field value is not between two given values: +`WhereNotBetween` usuli maydon qiymati berilgan ikki qiymat oralig'ida emasligini tekshiradi: ```go facades.DB().Table("users").WhereNotBetween("votes", 1, 100) @@ -394,7 +394,7 @@ facades.DB().Table("users").WhereNotBetween("votes", 1, 100) **WhereIn / WhereNotIn / OrWhereIn / OrWhereNotIn** -The `WhereIn` method verifies that a field value must exist in the specified array: +`WhereIn` usuli maydon qiymati belgilangan massivda mavjud bo'lishi kerakligini tekshiradi: ```go facades.DB().Table("users").WhereIn("id", []any{1, 2, 3}) @@ -402,7 +402,7 @@ facades.DB().Table("users").WhereIn("id", []any{1, 2, 3}) **WhereNull / WhereNotNull / OrWhereNull / OrWhereNotNull** -The `WhereNull` method verifies that a specified field must be `NULL`: +`WhereNull` usuli belgilangan maydon `NULL` bo'lishi kerakligini tekshiradi: ```go facades.DB().Table("users").WhereNull("updated_at") @@ -410,7 +410,7 @@ facades.DB().Table("users").WhereNull("updated_at") **WhereLike / WhereNotLike / OrWhereLike / OrWhereNotLike** -The `WhereLike` method verifies that a field value contains a given value: +`WhereLike` usuli maydon qiymati berilgan qiymatni o'z ichiga olishini tekshiradi: ```go facades.DB().Table("users").WhereLike("name", "%goravel%") @@ -418,15 +418,15 @@ facades.DB().Table("users").WhereLike("name", "%goravel%") **WhereColumn / OrWhereColumn** -The `WhereColumn` method verifies that two fields are equal: +`WhereColumn` usuli ikki maydonning tengligini tekshiradi: ```go facades.DB().Table("users").WhereColumn("first_name", "last_name") ``` -### Logical Grouping +### Mantiqiy guruhlash -Sometimes you may need to group several "where" clauses within parentheses to achieve the logical grouping required by your query. +Ba'zan so'rovingiz uchun zarur bo'lgan mantiqiy guruhlashni amalga oshirish uchun bir nechta "where" bandlarini qavs ichida guruhlashingiz kerak bo'lishi mumkin. ```go facades.DB().Table("users").Where("age", 25).Where(func(query db.Query) db.Query { @@ -434,9 +434,9 @@ facades.DB().Table("users").Where("age", 25).Where(func(query db.Query) db.Query }) ``` -## Ordering, Grouping, Limit & Offset +## Buyurtma berish, Guruhlash, Cheklash va O‘tkazib yuborish -### Ordering +### Tartiblash **OrderBy / OrderByDesc** @@ -446,9 +446,9 @@ facades.DB().OrderBy("name") facades.DB().OrderByDesc("name") ``` -**Latest** +**Oxirgi** -The `Latest` method makes it easy to sort results by date. By default, results will be sorted by the `created_at` column: +`Latest` usuli natijalarni sana bo'yicha tartiblashni osonlashtiradi. Standart bo‘yicha, natijalar `created_at` ustuni bo‘yicha tartiblanadi: ```go err := facades.DB().Table("users").Latest().First(&user) @@ -458,31 +458,31 @@ err := facades.DB().Table("users").Latest("updated_at").First(&user) **InRandomOrder** -The `InRandomOrder` method is used to sort results randomly: +`InRandomOrder` usuli natijalarni tasodifiy tartiblash uchun ishlatiladi: ```go err := facades.DB().Table("users").InRandomOrder().First(&user) ``` -### Grouping +### Guruhlash -The `GroupBy` and `Having` methods can be used to group results: +`GroupBy` va `Having` usullari natijalarni guruhlash uchun ishlatilishi mumkin: ```go err := facades.DB().Table("users").Where("age", 25).GroupBy("name").Having("name = ?", "John").OrderBy("name").Get(&users) ``` -### Limiting and Offset +### Cheklash va O‘tkazib yuborish -You can use the `Limit` and `Offset` methods to limit the number of results, or skip a specified number of results in the query: +Natijalar sonini cheklash yoki so'rovda belgilangan natijalar sonini o'tkazib yuborish uchun `Limit` va `Offset` metodlaridan foydalanishingiz mumkin: ```go err := facades.DB().Table("users").Offset(10).Limit(5).Get(&users) ``` -## Conditional Clauses +## Shartli bandlar -Sometimes you may want a clause to only execute when a given condition is true. For example, you may only want to apply a where clause when a given value exists in the request. You can accomplish this by using the `When` method: +Ba'zan siz berilgan shart to'g'ri bo'lganda faqat bir band bajarilishini xohlashingiz mumkin. Masalan, siz faqat so'rovda berilgan qiymat mavjud bo'lganda "where" bandini qo'llashni xohlashingiz mumkin. Buni `When` usuli yordamida amalga oshirishingiz mumkin: ```go import "github.com/goravel/framework/contracts/database/db" @@ -492,7 +492,7 @@ err := facades.DB().Table("users").When(1 == 1, func(query db.Query) db.Query { }).First(&user) ``` -You can also pass another closure as the third parameter to the `When` method. This closure will execute if the first parameter results in false: +Shuningdek, siz `When` metodining uchinchi parametri sifatida boshqa yopilishni ham o'tkazishingiz mumkin. Agar birinchi parametr yolg‘on bo‘lsa, bu yopilish bajariladi: ```go err := facades.DB().Table("users").When(1 != 1, func(query db.Query) db.Query { @@ -502,17 +502,17 @@ err := facades.DB().Table("users").When(1 != 1, func(query db.Query) db.Query { }).First(&user) ``` -## Insert +## Kiritish -The query builder provides the `Insert` method for inserting records into the database: +So'rov quruvchisi ma'lumotlar bazasiga yozuvlarni kiritish uchun `Insert` usulini taqdim etadi: ```go -// Insert by struct +// Struktura orqali kiritish result, err := facades.DB().Table("products").Insert(Product{ Name: "goravel", }) -// Insert by slice struct +// Strukturalar qatori orqali kiritish result, err := facades.DB().Table("products").Insert([]Product{ { Name: "goravel", @@ -522,14 +522,14 @@ result, err := facades.DB().Table("products").Insert([]Product{ }, }) -// Insert by map +// Xarita orqali kiritish result, err := facades.DB().Table("products").Insert(map[string]any{ "name": "goravel", "created_at": time.Now(), "updated_at": time.Now(), }) -// Insert by slice map +// Xaritalar qatori orqali kiritish result, err := facades.DB().Table("products").Insert([]map[string]any{ { "name": "goravel", @@ -544,9 +544,9 @@ result, err := facades.DB().Table("products").Insert([]map[string]any{ }) ``` -### Auto Increment ID +### Avtomatik oshiruvchi ID -If the table's primary key is auto increment, you can use the `LastInsertID` method to get the auto increment ID, only supported for `mysql` and `sqlite` databases: +Agar jadvalning asosiy kaliti avtomatik oshiriladigan bo'lsa, avtomatik oshirilgan IDni olish uchun `LastInsertID` usulidan foydalanishingiz mumkin, bu faqat `mysql` va `sqlite` ma'lumotlar bazalari uchun qo'llab-quvvatlanadi: ```go id, err := facades.DB().Table("products").InsertGetID(Product{ @@ -554,20 +554,20 @@ id, err := facades.DB().Table("products").InsertGetID(Product{ }) ``` -## Update +## Yangilash -The query builder provides the `Update` method for updating existing records in the database: +So'rov quruvchisi ma'lumotlar bazasidagi mavjud yozuvlarni yangilash uchun `Update` usulini taqdim etadi: ```go -// Update by field name +// Maydon nomi bo'yicha yangilash result, err := facades.DB().Table("products").Where("id", 1).Update("phone", "1234567890") -// Update by struct +// Struktura bo'yicha yangilash result, err := facades.DB().Table("products").Where("id", 1).Update(Product{ Name: "goravel", }) -// Update by map +// Xarita bo'yicha yangilash result, err := facades.DB().Table("products").Where("id", 1).Update(map[string]any{ "name": "goravel", "created_at": time.Now(), @@ -588,21 +588,21 @@ result, err := facades.DB().Table("users").Where("id", 1).Update(map[string]any{ }) ``` -### Update or Insert +### Yangilash yoki qo'shish -Sometimes you may want to update a record in the database, but if the specified record does not exist, create it. This can be done using the `UpdateOrInsert` method. The `UpdateOrInsert` method accepts two parameters: a condition for finding the record, and a key-value pair containing the values to update the record with. +Ba'zan siz ma'lumotlar bazasidagi yozuvni yangilamoqchi bo'lishingiz mumkin, lekin agar ko'rsatilgan yozuv mavjud bo'lmasa, uni yarating. Bu `UpdateOrInsert` usuli yordamida amalga oshirilishi mumkin. `UpdateOrInsert` usuli ikki parametrni qabul qiladi: yozuvni topish uchun shart va yozuvni yangilash uchun qiymatlarni o'z ichiga olgan kalit-qiymat juftligi. -The `UpdateOrInsert` method will attempt to locate a matching database record using the column names and values from the first parameter. If a record exists, its values will be updated using the second parameter. If no matching record is found, a record will be created and its values will be merged from the two parameters: +`UpdateOrInsert` usuli birinchi parametrdagi ustun nomlari va qiymatlari yordamida mos keladigan ma'lumotlar bazasi yozuvini topishga harakat qiladi. Agar yozuv mavjud bo'lsa, uning qiymatlari ikkinchi parametr yordamida yangilanadi. Agar mos yozuv topilmasa, yozuv yaratiladi va uning qiymatlari ikki parametrdan birlashtiriladi: ```go -// use struct +// struct-dan foydalanish result, err := facades.DB().Table("users").Where("id", 1).UpdateOrInsert(TestUser{ Email: "john@example.com", }, TestUser{ Phone: "1234567890", }) -// use map +// map-dan foydalanish result, err := facades.DB().Table("users").Where("id", 1).UpdateOrInsert(map[string]any{ "email": "john@example.com", }, map[string]any{ @@ -610,9 +610,9 @@ result, err := facades.DB().Table("users").Where("id", 1).UpdateOrInsert(map[str }) ``` -### Increment and Decrement +### Oshirish va Kamaytirish -The `Increment` and `Decrement` methods can be used to increment or decrement the value of a specified field: +`Increment` va `Decrement` metodlari belgilangan maydon qiymatini oshirish yoki kamaytirish uchun ishlatilishi mumkin: ```go err := facades.DB().Table("users").Where("id", 1).Increment("votes") @@ -624,44 +624,44 @@ err := facades.DB().Table("users").Where("id", 1).Decrement("votes") err := facades.DB().Table("users").Where("id", 1).Decrement("votes", 2) ``` -## Delete +## O‘chirish -The query builder also includes some functions that can help you implement "pessimistic locking" in your `select` statements: +So'rov quruvchisi shuningdek, sizning `select` gaplaringizda "pessimistik qulflash"ni amalga oshirishingizga yordam beradigan ba'zi funksiyalarni o'z ichiga oladi: ```go -result, err := facades.DB().Table("users").Where("id", 1).Delete() +natija, xato := facades.DB().Table("users").Where("id", 1).Delete() ``` -## Pessimistic Locking +## Pessimistik blokirovka -The query builder also includes some functions that can help you implement "pessimistic locking" in your `select` statements: +So'rov quruvchisi, shuningdek, sizning `select` bayonotlaringizda "pessimistik qulflash"ni amalga oshirishga yordam beradigan ba'zi funksiyalarni o'z ichiga oladi: -To use a "shared lock", you may use the `SharedLock` method. A shared lock prevents the selected rows from being modified until the transaction is committed: +"Umumiy qulflash"dan foydalanish uchun siz `SharedLock` usulidan foydalanishingiz mumkin. "Umumiy qulf" tanlangan qatorlar transaksiya tasdiqlanmaguncha o'zgartirilishiga yo'l qo'ymaydi: ```go -err := facades.DB().Table("users").Where("votes > ?", 100).SharedLock().Get(&users) +err := facades.DB().Table("users").Where("ovozlar > ?", 100).SharedLock().Get(&users) ``` -You can also use the `LockForUpdate` method. Using the "update" lock can prevent rows from being modified or selected by other shared locks: +Shuningdek, siz `LockForUpdate` usulidan foydalanishingiz mumkin. "Yangilash" qulfidan foydalanish qatorlarni boshqa umumiy qulf tomonidan o'zgartirilishiga yoki tanlanishiga to'sqinlik qilishi mumkin: ```go err := facades.DB().Table("users").Where("votes > ?", 100).LockForUpdate().Get(&users) ``` -## Debugging +## Debuglash -You can use the `ToSQL` and `ToRawSql` methods to get the current query binding and SQL. +Joriy so'rovni bog'lash va SQLni olish uchun `ToSQL` va `ToRawSql` usullaridan foydalanishingiz mumkin. -With placeholder SQL: +SQL joylashtirgich bilan: ```go err := facades.DB().Table("users").Where("id", 1).ToSql().Get(models.User{}) ``` -With bound values SQL: +SQL bilan bog'langan qiymatlar: ```go err := facades.DB().Table("users").Where("id", 1).ToRawSql().Get(models.User{}) ``` -The methods that can be called after `ToSql` and `ToRawSql`: `Count`, `Insert`, `Delete`, `First`, `Get`, `Pluck`, `Update`. +`ToSql` va `ToRawSql` dan keyin chaqirilishi mumkin bo'lgan metodlar: `Count`, `Insert`, `Delete`, `First`, `Get`, `Pluck`, `Update`. From 11c2889ad48c1039cdc9b1811825669c7d7de200 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Wed, 1 Apr 2026 18:53:04 +0800 Subject: [PATCH 087/163] New translations seeding.md (Uzbek) [skip ci] Update translations (Uzbek) seeding.md --- uz_UZ/database/seeding.md | 42 +++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/uz_UZ/database/seeding.md b/uz_UZ/database/seeding.md index 8531ee9bf..c59d18c09 100644 --- a/uz_UZ/database/seeding.md +++ b/uz_UZ/database/seeding.md @@ -1,25 +1,25 @@ -# Database: Seeding +# Ma'lumotlar bazasi: Urg'ochi qo'shish [[toc]] -## Introduction +## Kirish -Goravel includes the ability to seed your database with data using seed struct. All seed structs are stored in the `database/seeders` directory. By default, a `DatabaseSeeder` struct is defined for you. +Goravel ma'lumotlar bazangizni seed struct yordamida ma'lumotlar bilan to'ldirish imkoniyatini o'z ichiga oladi. Barcha urug' strukturalari `database/seeders` katalogida saqlanadi. Standart bo‘yicha, siz uchun `DatabaseSeeder` struktura belgilangan. -## Writing Seeders +## Seederlarni yozish -To generate a seeder, run the `make:seeder` [Artisan command](../digging-deeper/artisan-console.md). All seeders generated by the framework will be stored in the `database/seeders` directory: +Seeder yaratish uchun `make:seeder` [Artisan buyrug'ini](../digging-deeper/artisan-console.md) ishga tushiring. Framework tomonidan yaratilgan barcha urug‘lar `database/seeders` katalogida saqlanadi: ```shell ./artisan make:seeder UserSeeder ``` -By default, a seeder struct has two methods: `Signature` and `Run`. The `Signature` method sets the name of the seeder, while the `Run` method is triggered when the `db:seed` Artisan command is executed. You can use the `Run` method to insert data into your database in any way you prefer. +Standart bo'yicha, seeder strukturasida ikkita metod mavjud: `Signature` va `Run`. `Signature` usuli seeder nomini belgilaydi, `Run` usuli esa `db:seed` Artisan buyrug'i bajarilganda ishga tushiriladi. Siz ma'lumotlarni o'zingiz xohlagan tarzda ma'lumotlar bazangizga kiritish uchun `Run` metodidan foydalanishingiz mumkin. -To illustrate, we can customize the `DatabaseSeeder` struct by adding a database insert statement to the `Run` method. +Masalan, biz `DatabaseSeeder` strukturini `Run` metodiga ma'lumotlar bazasiga ma'lumot kiritish bayonotini qo'shish orqali sozlashimiz mumkin. ```go -package seeders +paket urug‘chilari import ( "github.com/goravel/framework/contracts/database/seeder" @@ -31,12 +31,12 @@ import ( type DatabaseSeeder struct { } -// Signature The name and signature of the seeder. +// Imzo Urg‘uchining nomi va imzosi. func (s *DatabaseSeeder) Signature() string { return "DatabaseSeeder" } -// Run executes the seeder logic. +// Run urg‘uchi mantiqini bajaradi. func (s *DatabaseSeeder) Run() error { user := models.User{ Name: "goravel", @@ -45,12 +45,12 @@ func (s *DatabaseSeeder) Run() error { } ``` -## Calling Additional Seeders +## Qo'shimcha Seederni chaqirish -Within the `DatabaseSeeder` struct, you may use the `Call` method to execute additional seed structs. Using the `Call` method allows you to break up your database seeding into multiple files so that no single seeder struct becomes too large. The `Call` method accepts an array of seeder structs that should be executed: +`DatabaseSeeder` strukturasi ichida, qo'shimcha urug' strukturalarini bajarish uchun `Call` metodidan foydalanishingiz mumkin. `Call` usulidan foydalanish ma'lumotlar bazangizni ko'chirishni bir nechta fayllarga bo'lish imkonini beradi, shunda biron bir ko'chiruvchi struktura juda katta bo'lib qolmaydi. `Call` usuli bajarilishi kerak bo'lgan seeder strukturalari massivini qabul qiladi: ```go -// Run executes the seeder logic. +// Run seeder mantiqini bajaradi. func (s *DatabaseSeeder) Run() error { return facades.Seeder().Call([]seeder.Seeder{ &UserSeeder{}, @@ -58,10 +58,10 @@ func (s *DatabaseSeeder) Run() error { } ``` -Framework also provides a `CallOnce` method, a seeder will be executed only once in the `db:seed` command: +Framework shuningdek `CallOnce` usulini taqdim etadi, bu urug‘lantiruvchi `db:seed` buyrug‘ida faqat bir marta bajariladi: ```go -// Run executes the seeder logic. +// Run seeder mantiqini bajaradi. func (s *DatabaseSeeder) Run() error { return facades.Seeder().CallOnce([]seeder.Seeder{ &UserSeeder{}, @@ -69,15 +69,15 @@ func (s *DatabaseSeeder) Run() error { } ``` -## Running Seeders +## Seederlarni ishga tushirish -You may run the `db:seed` Artisan command to seed your database. By default, the `db:seed` command runs the `database/seeders/database_seeder.go` file, which may in turn invoke other seed classes. However, you may use the `--seeder` option to specify a specific seeder class to run individually: +Siz ma'lumotlar bazangizni to'ldirish uchun `db:seed` Artisan buyrug'ini ishga tushirishingiz mumkin. Standart holatda, `db:seed` buyrug'i `database/seeders/database_seeder.go` faylini ishga tushiradi, bu esa o'z navbatida boshqa urug' sinflarini chaqirishi mumkin. Biroq, siz `--seeder` opsiyasidan foydalanib, alohida ishlatish uchun aniq seeder klassini belgilashingiz mumkin: ```shell ./artisan db:seed ``` -If you want to execute other seeders when running the `db:seed` command, you can register the seeder in the `bootstrp/app.go::WithSeeders` function, if the seeder is generated by the `make:seeder` command, the framework will automatically register it. +Agar siz `db:seed` buyrug'ini ishga tushirganda boshqa seederlarni bajarishni istasangiz, seeder-ni `bootstrp/app.go::WithSeeders` funksiyasida ro'yxatdan o'tkazishingiz mumkin. Agar seeder `make:seeder` buyrug'i orqali yaratilgan bo'lsa, framework uni avtomatik ravishda ro'yxatdan o'tkazadi. ```go func Boot() contractsfoundation.Application { @@ -90,7 +90,7 @@ func Boot() contractsfoundation.Application { ./artisan db:seed --seeder=UserSeeder PhotoSeeder // The signature of seeder ``` -You may also seed your database using the `migrate:fresh` and `migrate:refresh` command in combination with the `--seed` option, which will drop all tables and re-run all of your migrations. This command is useful for completely re-building your database. The `--seeder` option may be used to specify a specific seeder to run: +Shuningdek, siz ma'lumotlar bazangizni `migrate:fresh` va `migrate:refresh` buyruqlarini `--seed` opsiyasi bilan birgalikda ishlatib, to'ldirishingiz mumkin. Bu barcha jadvallarni o'chirib tashlaydi va barcha migratsiyalaringizni qayta ishga tushiradi. Bu buyruq ma'lumotlar bazangizni to'liq qayta qurish uchun foydalidir. `--seeder` opsiyasi ma'lum bir seeder-ni ishga tushirish uchun ko'rsatish mumkin: ```shell ./artisan migrate:fresh --seed @@ -102,9 +102,9 @@ You may also seed your database using the `migrate:fresh` and `migrate:refresh` ./artisan migrate:refresh --seed --seeder=UserSeeder ``` -### Forcing Seeders To Run In Production +### Ishlab chiqarish muhitida urug‘chilarni majburiy ishga tushirish -Some seeding operations may cause you to alter or lose data. In order to protect you from running seeding commands against your production database, you will be prompted for confirmation before the seeders are executed in the `production` environment. To force the seeders to run without a prompt, use the `--force` flag: +Ba'zi urug'lantirish amallari ma'lumotlarni o'zgartirish yoki yo'qotishga olib kelishi mumkin. "production" muhitida urug'lar bajarilishidan oldin tasdiqlash so'raladi, shunda sizning ishlab chiqarish ma'lumotlar bazangizga urug' buyruqlarini ishga tushirishdan himoya qilinishingiz uchun. Seederlarni so'ralsiz ishga tushirish uchun `--force` bayrog'idan foydalaning: ```shell ./artisan db:seed --force From 30586981cbe6bcc74f229518f9cee2570d2ba2b3 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Wed, 1 Apr 2026 18:53:06 +0800 Subject: [PATCH 088/163] New translations artisan-console.md (Uzbek) [skip ci] Update translations (Uzbek) artisan-console.md --- uz_UZ/digging-deeper/artisan-console.md | 269 ++++++++++++------------ 1 file changed, 134 insertions(+), 135 deletions(-) diff --git a/uz_UZ/digging-deeper/artisan-console.md b/uz_UZ/digging-deeper/artisan-console.md index 98fdf24ee..7b7da40c8 100644 --- a/uz_UZ/digging-deeper/artisan-console.md +++ b/uz_UZ/digging-deeper/artisan-console.md @@ -1,50 +1,50 @@ -# Artisan Console +# Artisan Konsoli [[toc]] -## Introduction +## Kirish -Artisan is the CLI tool that comes with Goravel for interacting with the command line. You can access it using `facades.Artisan()`. This tool has several useful commands that can assist you in the development of your application. Utilize the following command to view all available commands. +Artisan - Goravel bilan birga keladigan, buyruq qatori bilan ishlash uchun CLI vositasidir. Siz uni `facades.Artisan()` yordamida ochishingiz mumkin. Ushbu vosita sizning ilovangizni rivojlantirishda yordam beradigan bir nechta foydali buyruqlarga ega. Barcha mavjud buyruqlarni ko'rish uchun quyidagi buyruqdan foydalaning. ```shell -./artisan list +./artisan ro'yxat -# or -go run . artisan list +# yoki +go run . artisan ro'yxat ``` -Each command also has a "help" flag that shows and explains the arguments and options associated with the command: +Har bir buyruq shuningdek, buyruq bilan bog'liq argumentlar va opsiyalarni ko'rsatadigan va tushuntiradigan "yordam" bayrog'iga ega: ```shell -./artisan migrate --help +./artisan migrate --yordam ``` -Instead of repeating `./artisan ...` command, you may want to add an alias to your shell configuration with the terminal command below: +`./artisan ...` buyrug'ini takrorlash o'rniga, quyidagi terminal buyrug'i bilan o'z shell konfiguratsiyangizga taxallus qo'shishingiz mumkin: ```shell echo -e "\r\nalias artisan=\"go run . artisan\"" >>~/.zshrc ``` -Then you can simply run your commands like this: +Keyin siz buyruqlaringizni shunchaki shunday ishga tushirishingiz mumkin: ```shell artisan make:controller DemoController ``` -You can also use `artisan` shell script like this: +Shuningdek, siz `artisan` shell skriptidan shunday foydalanishingiz mumkin: -### Generating Commands +### Buyruqlarni yaratish -You can use the `make:command` command to create a new command in the `app/console/commands` directory. Don't worry if this directory does not exist in your application, it will be created the first time you run the `make:command` command: +Siz `make:command` buyrug'idan `app/console/commands` katalogida yangi buyruq yaratish uchun foydalanishingiz mumkin. Agar bu katalog sizning ilovangizda mavjud bo'lmasa, tashvishlanmang, u siz `make:command` buyrug'ini birinchi marta ishga tushirganingizda yaratiladi: ```shell ./artisan make:command SendEmails ./artisan make:command user/SendEmails ``` -### Register Commands +### Buyruqlarni ro'yxatdan o'tkazish -All commands should be registered via the `WithCommands` function in the `bootstrap/app.go` file: +Barcha buyruqlar `bootstrap/app.go` faylidagi `WithCommands` funksiyasi orqali ro'yxatdan o'tkazilishi kerak: ```go func Boot() contractsfoundation.Application { @@ -55,14 +55,14 @@ func Boot() contractsfoundation.Application { } ``` -A new command created by `make:command` will be registered automatically in the `bootstrap/commands.go::Commands()` function and the function will be called by `WithCommands`. You need register the command manually if you create the command file by yourself. +`make:command` tomonidan yaratilgan yangi buyruq `bootstrap/commands.go::Commands()` funksiyasida avtomatik ro'yxatdan o'tkaziladi va funksiya `WithCommands` tomonidan chaqiriladi. Agar buyruq faylini o'zingiz yaratgan bo'lsangiz, buyruqni qo'lda ro'yxatdan o'tkazishingiz kerak. -### Command Structure +### Buyruq tuzilmasi -After generating your command, assign suitable values to the signature and description properties of the struct. The `Handle` method will be called when your command is executed. You need to implement your logic in this method. +Buyruqni yaratgandan so'ng, structning signature va description xususiyatlariga mos qiymatlarni belgilang. Buyruq bajarilganda `Handle` usuli chaqiriladi. Siz ushbu metodda o'z mantiqingizni amalga oshirishingiz kerak. ```go -package commands +paket buyruqlari import ( "github.com/goravel/framework/contracts/console" @@ -72,88 +72,87 @@ import ( type SendEmails struct { } -// Signature The name and signature of the console command. +// Imzo Konsol buyrug'ining nomi va imzosi. func (receiver *SendEmails) Signature() string { return "send:emails" } -// Description The console command description. +// Tavsif Konsol buyrug'ining tavsifi. func (receiver *SendEmails) Description() string { - return "Send emails" + return "Elektron pochta xabarlarini yuborish" } -// Extend The console command extend. +// Kengaytma Konsol buyrug'ining kengaytmasi. func (receiver *SendEmails) Extend() command.Extend { return command.Extend{} } -// Handle Execute the console command. +// Boshqarish Konsol buyrug'ini bajarish. func (receiver *SendEmails) Handle(ctx console.Context) error { return nil } ``` -## Command I/O +## Buyruq kirish/chiqish -### Retrieving Input +### Kirishni olish -When you write console commands, it's typical to collect user input through `arguments` or `options`. With Goravel, it's extremely easy to retrieve the arguments and options that the user provides. +Konsol buyruqlarini yozishda, odatda foydalanuvchi kiritimini `argumentlar` yoki `opsiyalar` orqali yigʻish mumkin. Goravel bilan foydalanuvchi taqdim etgan argumentlar va opsiyalarni olish juda oson. -#### Arguments +#### Argumentlar -Follow the arguments after the command: +Buyruqdan keyingi argumentlarni kuzating: ```shell ./artisan send:emails SUBJECT EMAIL_1 EMAIL_2 ``` -Definition: +Ta'rif: ```go -// send:emails +// send:emails <0> <1> func (receiver *SendEmails) Extend() command.Extend { return command.Extend{ Arguments: []command.Argument{ &command.ArgumentString{ Name: "subject", - Usage: "subject of email", + Usage: "elektron pochta mavzusi", Required: true, }, &command.ArgumentStringSlice{ Name: "emails", - Usage: "target emails", + Usage: "maqsadli elektron pochta manzillari", Min: 1, Max: -1, }, }, } -} ``` -Supported agrument types : `ArgumentFloat32`, `ArgumentFloat64`, `ArgumentInt`, `ArgumentInt8`, `ArgumentInt16`, `ArgumentInt32`, `ArgumentInt64`, `ArgumentString`, `ArgumentUint`, `ArgumentUint8`, `ArgumentUint16`, `ArgumentUint32`, `ArgumentUint64`, `ArgumentTimestamp`, `ArgumentFloat32Slice`, `ArgumentFloat64Slice`, `ArgumentIntSlice`, `ArgumentInt8Slice`, `ArgumentInt16Slice`, `ArgumentInt32Slice`, `ArgumentInt64Slice`, `ArgumentStringSlice`, `ArgumentUintSlice`, `ArgumentUint8Slice`, `ArgumentUint16Slice`, `ArgumentUint32Slice`, `ArgumentUint64Slice`, `ArgumentTimestampSlice` +Qo'llab-quvvatlanadigan argument turlari: `ArgumentFloat32`, `ArgumentFloat64`, `ArgumentInt`, `ArgumentInt8`, `ArgumentInt16`, `ArgumentInt32`, `ArgumentInt64`, `ArgumentString`, `ArgumentUint`, `ArgumentUint8`, `ArgumentUint16`, `ArgumentUint32`, `ArgumentUint64`, `ArgumentTimestamp`, `ArgumentFloat32Slice`, `ArgumentFloat64Slice`, `ArgumentIntSlice`, `ArgumentInt8Slice`, `ArgumentInt16Slice`, `ArgumentInt32Slice`, `ArgumentInt64Slice`, `ArgumentStringSlice`, `ArgumentUintSlice`, `ArgumentUint8Slice`, `ArgumentUint16Slice`, `ArgumentUint32Slice`, `ArgumentUint64Slice`, `ArgumentTimestampSlice` -Argument types with single value support next fields: +Bitta qiymatni qo‘llab-quvvatlovchi argument turlari quyidagi maydonlarni qo‘llab-quvvatlaydi: ```go - Name string // the name of this argument - Value T // the default value of this argument - Usage string // the usage text to show - Required bool // if this argument is required + Ism string // bu argumentning nomi + Qiymat T // bu argumentning standart qiymati + Foydalanish string // ko'rsatish uchun foydalanish matni + Majburiy bool // agar bu argument majburiy bo'lsa ``` -Slice argument types fields: +"Slice" argument turlari maydonlari: ```go - Name string // the name of this argument - Value T // the default value of this argument - Usage string // the usage text to show - Min int // the min num of occurrences of this argument - Max int // the max num of occurrences of this argument, set to -1 for unlimited + Ism string // bu argumentning nomi + Qiymat T // bu argumentning standart qiymati + Foydalanish string // ko'rsatiladigan foydalanish matni + Min int // bu argumentning minimal takrorlanish soni + Max int // bu argumentning maksimal takrorlanish soni, cheksiz uchun -1 ga o'rnating ``` -Timestamp arguments additionally supports `Layouts []string` field, that should be filled with [supported layouts](https://pkg.go.dev/time#pkg-constants) +Timestamp argumentlari qo'shimcha ravishda `Layouts []string` maydonini qo'llab-quvvatlaydi, bu [qo'llab-quvvatlanadigan layoutlar](https://pkg.go.dev/time#pkg-constants) bilan to'ldirilishi kerak -Get arguments: +Argumentlarni oling: ```go func (receiver *SendEmails) Handle(ctx console.Context) error { @@ -164,23 +163,23 @@ func (receiver *SendEmails) Handle(ctx console.Context) error { } ``` -Alternatively, it is possible to access arguments directly: +Boshqa yo'l sifatida, argumentlarga to'g'ridan-to'g'ri kirish mumkin: ```go -func (receiver *SendEmails) Handle(ctx console.Context) error { - name := ctx.Argument(0) +func (qabul qiluvchi *EmailYuborish) Boshqarish(ctx console.Context) xato { + ism := ctx.Argument(0) email := ctx.Argument(1) - all := ctx.Arguments() + hammasi := ctx.Arguments() return nil } ``` -#### Options +#### Parametrlar -Options, like arguments, are another form of user input. Options are prefixed by two hyphens (--) when they are provided via the command line. +Opsiyalar, argumentlar singari, foydalanuvchi kiritishining yana bir shaklidir. Parametrlar buyruq qatori orqali taqdim etilganda, ikkita tire (--) bilan boshlanadi. -Definition: +Ta'rif: ```go func (receiver *ListCommand) Extend() command.Extend { @@ -190,86 +189,86 @@ func (receiver *ListCommand) Extend() command.Extend { Name: "lang", Value: "default", Aliases: []string{"l"}, - Usage: "language for the greeting", + Usage: "salomlashish uchun til", }, }, } } ``` -Get: +Oling: ```go -func (receiver *ListCommand) Handle(ctx console.Context) error { - lang := ctx.Option("lang") +func (qabul qiluvchi *ListCommand) Handle(ctx console.Context) xato { + til := ctx.Option("til") return nil } ``` -Usage: +Foydalanish: ```shell -./artisan emails --lang Chinese -./artisan emails -l Chinese +./artisan emails --lang Xitoy +./artisan emails -l Xitoy ``` -Except `command.StringFlag`, we can also use other type `Flag` and `Option*`: `StringSliceFlag`, `BoolFlag`, `Float64Flag`, `Float64SliceFlag`, `IntFlag`, `IntSliceFlag`, `Int64Flag`, `Int64SliceFlag`. +`command.StringFlag` dan tashqari, biz boshqa turdagi `Flag` va `Option*` lardan ham foydalanishimiz mumkin: `StringSliceFlag`, `BoolFlag`, `Float64Flag`, `Float64SliceFlag`, `IntFlag`, `IntSliceFlag`, `Int64Flag`, `Int64SliceFlag`. -### Prompting For Input +### Kirishni So'rash -#### Asking Questions +#### Savollar berish -In addition to arguments and options, you may also prompt the user for input during the execution of a command. The `Ask` method will prompt the user with the given question and return their response: +Argumentlar va opsiyalardan tashqari, siz buyruq bajarilayotganda foydalanuvchidan kirish so'rashingiz mumkin. `Ask` usuli foydalanuvchiga berilgan savolni ko'rsatadi va ularning javobini qaytaradi: ```go func (receiver *SendEmails) Handle(ctx console.Context) error { - email, err := ctx.Ask("What is your email address?") + email, err := ctx.Ask("Elektron pochta manzilingiz nima?") return err } ``` -Additionally, you can pass options to the `Ask` method as optional second argument: +Bundan tashqari, `Ask` metodiga opsiyalarni ixtiyoriy ikkinchi argument sifatida o‘tkazishingiz mumkin: ```go -func (receiver *SendEmails) Handle(ctx console.Context) error { - name, err := ctx.Ask("What is your name?", console.AskOption{ +func (qabul qiluvchi *SendEmails) Handle(ctx console.Context) xato { + ism, xato := ctx.Ask("Ismingiz nima?", console.AskOption{ Default: "Krishan", }) - return err + return xato } -// Available options +// Mavjud opsiyalar type AskOption struct { - // Default the default value for the input. + // Default - kiritish uchun standart qiymat. Default string - // Description the input description. + // Description - kiritish tavsifi. Description string - // Lines the number of lines for the input.(use for multiple lines text) + // Lines - kiritish uchun qatorlar soni.(ko'p qatorli matn uchun ishlatiladi) Lines int - // Limit the character limit for the input. + // Limit - kiritish uchun belgilar chegarasi. Limit int - // Multiple determines if input is single line or multiple lines text + // Multiple - kiritish bitta qator yoki ko'p qatorli matn ekanligini aniqlaydi Multiple bool - // Placeholder the input placeholder. + // Placeholder - kiritish uchun joy egallovchi. Placeholder string - // Prompt the prompt message.(use for single line input) + // Prompt - so'rov xabari.(bitta qatorli kiritish uchun ishlatiladi) Prompt string - // Validate the input validation function. - Validate func(string) error + // Validate - kiritishni tekshirish funksiyasi. + Validate func(string) xato } ``` -Sometimes you may need to hide the user input, such as when prompting for a password. You can use the `Secret` method to hide the user input: +Ba'zan foydalanuvchi kiritishini yashirish kerak bo'lishi mumkin, masalan, parol so'rashda. Siz foydalanuvchi kiritishini yashirish uchun `Secret` usulidan foydalanishingiz mumkin: ```go func (receiver *SendEmails) Handle(ctx console.Context) error { - password, err := ctx.Secret("What is the password?", console.SecretOption{ + password, err := ctx.Secret("Parol nima?", console.SecretOption{ Validate: func (s string) error { if len(s) < 8 { - return errors.New("password length should be at least 8") + return errors.New("parol uzunligi kamida 8 bo'lishi kerak") } return nil }, @@ -278,32 +277,32 @@ func (receiver *SendEmails) Handle(ctx console.Context) error { return err } -// Available options +// Mavjud variantlar type SecretOption struct { - // Default the default value for the input. + // Default - kiritish uchun standart qiymat. Default string - // Description the input description. + // Description - kiritish tavsifi. Description string - // Limit the character limit for the input. + // Limit - kiritish uchun belgilar chegarasi. Limit int - // Placeholder the input placeholder. + // Placeholder - kiritish uchun belgilovchi. Placeholder string - // Validate the input validation function. + // Validate - kiritishni tekshirish funksiyasi. Validate func(string) error } ``` -#### Confirming Actions +#### Amallarni tasdiqlash -If you need to ask the user to confirm an action before proceeding, you may use the `Confirm` method. By default, this method will return `false` unless the user select affirmative option. +Agar foydalanuvchidan harakatni davom ettirishdan oldin tasdiqlashni so'rashingiz kerak bo'lsa, `Confirm` usulidan foydalanishingiz mumkin. Standart holatda, ushbu metod foydalanuvchi ijobiy variantni tanlamaguncha `false` qiymatini qaytaradi. ```go -if ctx.Confirm("Do you wish to continue?") { +agar ctx.Confirm("Davom etishni xohlaysizmi?") { // ... } ``` -You can also pass a second argument to the `Confirm` method to customize the default value, label of the affirmative and negative buttons: +Shuningdek, siz `Confirm` usuliga ikkinchi argument berib, standart qiymatni, ijobiy va salbiy tugmalarning yorlig'ini sozlashingiz mumkin: ```go if ctx.Confirm("Do you wish to continue?", console.ConfirmOption{ @@ -327,9 +326,9 @@ type ConfirmOption struct { } ``` -#### Single Select Questions +#### Bitta tanlovli savollar -If you need to ask the user to select an option from a list of options, you may use the `Choice` method. The `Choice` method will return the value of the selected option: +Agar foydalanuvchidan ro'yxatdan variant tanlashni so'rashingiz kerak bo'lsa, `Choice` usulidan foydalanishingiz mumkin. `Choice` usuli tanlangan variantning qiymatini qaytaradi: ```go question := "What is your favorite programming language?" @@ -342,7 +341,7 @@ options := []console.Choice{ color, err := ctx.Choice(question, options) ``` -Additionally, you can pass options to the `Choice` method as optional second argument: +Shuningdek, siz `Choice` usuliga ixtiyoriy ikkinchi argument sifatida opsiyalarni o‘tkazishingiz mumkin: ```go question := "What is your favorite programming language?" @@ -368,9 +367,9 @@ type ChoiceOption struct { } ``` -#### Multiple Select Questions +#### Ko'p tanlovli savollar -If you need to ask the user to select multiple options from a list of options, you may use the `MultiSelect` method. The `MultiSelect` method will return the values of the selected options: +Agar foydalanuvchidan ro'yxatdan bir nechta variantlarni tanlashni so'rashingiz kerak bo'lsa, `MultiSelect` usulidan foydalanishingiz mumkin. `MultiSelect` usuli tanlangan variantlarning qiymatlarini qaytaradi: ```go question := "What are your favorite programming languages?" @@ -383,7 +382,7 @@ options := []console.Choice{ colors, err := ctx.MultiSelect(question, options) ``` -Additionally, you can pass options to the `MultiSelect` method as optional second argument: +Bundan tashqari, siz `MultiSelect` usuliga ixtiyoriy ikkinchi argument sifatida variantlarni o‘tkazishingiz mumkin: ```go question := "What are your favorite programming languages?" @@ -413,47 +412,47 @@ type MultiSelectOption struct { } ``` -### Writing Output +### Chiqish yozish -Sometimes you may need to write output to the console. Goravel provides several methods to assist you in writing output to the console. Each of the method have their appropriate colorized output. For example, `Error` will display the text in red. +Ba'zan siz konsolga chiqish yozishingiz kerak bo'lishi mumkin. Goravel sizga konsolga chiqish yozishda yordam beradigan bir nechta usullarni taqdim etadi. Har bir metod o'ziga xos rangli chiqishga ega. Masalan, `Error` matnni qizil rangda ko'rsatadi. ```go func (receiver *SendEmails) Handle(ctx console.Context) error { - ctx.Comment("This is a comment message") - ctx.Info("This is an info message") - ctx.Error("This is an error message") - ctx.Line("This is a line message") - ctx.Warning("This is a warning message") + ctx.Comment("Bu izoh xabari") + ctx.Info("Bu ma'lumot xabari") + ctx.Error("Bu xato xabari") + ctx.Line("Bu qator xabari") + ctx.Warning("Bu ogohlantirish xabari") return nil } ``` -There are few helpers to write to console with respective color: +Mos rangga mos yozish uchun bir nechta yordamchilar mavjud: ```go -ctx.Green("This is a green message") -ctx.Greenln("This is a green line message") -ctx.Red("This is a red message") -ctx.Redln("This is a red line message") -ctx.Yellow("This is a yellow message") -ctx.Yellowln("This is a yellow line message") -ctx.Black("This is a black message") -ctx.Blackln("This is a black line message") +ctx.Green("Bu yashil xabar") +ctx.Greenln("Bu yashil chiziqli xabar") +ctx.Red("Bu qizil xabar") +ctx.Redln("Bu qizil chiziqli xabar") +ctx.Yellow("Bu sariq xabar") +ctx.Yellowln("Bu sariq chiziqli xabar") +ctx.Black("Bu qora xabar") +ctx.Blackln("Bu qora chiziqli xabar") ``` -You can use the `NewLine` method to write a new line to the console: +Siz `NewLine` usulidan foydalanib konsolga yangi qator yozishingiz mumkin: ```go -// write single blank line +// bitta bo'sh qator yozish ctx.NewLine() -// write multiple blank lines +// bir nechta bo'sh qatorlar yozish ctx.NewLine(2) ``` #### Progress Bars -For long-running tasks, it is often helpful to provide the user with some indication of how much time the task will take. You may use the `WithProgressBar` method to display a progress bar. +Uzoq davom etadigan vazifalar uchun, foydalanuvchiga vazifa qancha vaqt oladi haqida ma'lumot berish foydali bo'ladi. Siz taraqqiyot panelini ko'rsatish uchun `WithProgressBar` usulidan foydalanishingiz mumkin. ```go items := []any{"item1", "item2", "item3"} @@ -463,7 +462,7 @@ _, err := ctx.WithProgressBar(items, func(item any) error { }) ``` -Sometimes you may need to update the progress bar manually. You can use the `CreateProgressBar` method to update the progress bar: +Ba'zan siz progress bar-ni qo'lda yangilashingiz kerak bo'lishi mumkin. Siz progress bar-ni yangilash uchun `CreateProgressBar` usulidan foydalanishingiz mumkin: ```go users := []string{"user1", "user2", "user3"} @@ -482,35 +481,35 @@ for _, user := range users { err = bar.Finish() ``` -#### Spinner +#### Aylana -If you need to display a spinner while a task is running, you may use the `Spinner` method. +Agar vazifa bajarilayotganda spinner ko'rsatish kerak bo'lsa, `Spinner` metodidan foydalanishingiz mumkin. ```go -err := ctx.Spinner("Loading...", console.SpinnerOption{ +err := ctx.Spinner("Yuklanmoqda...", console.SpinnerOption{ Action: func() error { - // when to stop the spinner + // spinner qachon to'xtatilishi kerak time.Sleep(2 * time.Second) return nil }, }) ``` -### Divider +### Ajratgich -To show terminal-width divider you may use `Divider` method. +Terminal kengligidagi ajratuvchini ko'rsatish uchun `Divider` metodidan foydalanishingiz mumkin. ```go ctx.Divider() // ---------- ctx.Divider("=>") // =>=>=>=>=> ``` -## Category +## Kategoriya -You can set a set of commands to the same category, convenient in `./artisan list`: +Siz bir qator buyruqlarni bir xil kategoriyaga o'rnatishingiz mumkin, bu `./artisan list` da qulay: ```go -// Extend The console command extend. +// Konsol buyrug'ini kengaytirish. func (receiver *ConsoleMakeCommand) Extend() command.Extend { return command.Extend{ Category: "make", @@ -518,9 +517,9 @@ func (receiver *ConsoleMakeCommand) Extend() command.Extend { } ``` -## Programmatically Executing Commands +## Dasturiy tarzda buyruqlarni bajarish -Sometimes you may wish to execute an Artisan command outside of the CLI, you can use the `Call` method on the `facades.Artisan()` to operate this. +Ba'zan siz Artisan buyrug'ini CLI tashqarisida bajarishingiz mumkin, buning uchun `facades.Artisan()` da `Call` metodidan foydalanishingiz mumkin. ```go facades.Route().Get("/", func(c *gin.Context) { @@ -529,10 +528,10 @@ facades.Route().Get("/", func(c *gin.Context) { }) ``` -## Disabling Print Colors +## Chop etish ranglarini o‘chirish -Some commands print colors by default, such as the `list` command. However, in some terminals or logs, the color values may be garbled. You can use the `--no-ansi` option to disable the print colors: +Ba'zi buyruqlar standart ravishda ranglarni chiqaradi, masalan, `list` buyrug'i. Biroq, ba'zi terminal yoki jurnallarda rang qiymatlari noto'g'ri ko'rsatilishi mumkin. Siz chop ranglarini o'chirish uchun `--no-ansi` opsiyasidan foydalanishingiz mumkin: ```shell -./artisan list --no-ansi +./artisan ro'yxat --no-ansi ``` From 3ef09308f417b98d69961f0a5d50a4411a0a0a25 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Wed, 1 Apr 2026 18:53:07 +0800 Subject: [PATCH 089/163] New translations cache.md (Uzbek) [skip ci] Update translations (Uzbek) cache.md --- uz_UZ/digging-deeper/cache.md | 102 +++++++++++++++++----------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/uz_UZ/digging-deeper/cache.md b/uz_UZ/digging-deeper/cache.md index f34a8f919..5ca3d271c 100644 --- a/uz_UZ/digging-deeper/cache.md +++ b/uz_UZ/digging-deeper/cache.md @@ -1,36 +1,36 @@ -# Cache +# Kesh [[toc]] -## Introduction +## Kirish -Goravel provides an expandable cache module that can be operated using `facades.Cache()`. Goravel comes with a `memory` driver, for other drivers, please check the corresponding independent extension packages: +Goravel kengaytiriladigan keshlash modulini taqdim etadi, uni `facades.Cache()` yordamida boshqarish mumkin. Goravel "memory" haydovchisi bilan birga keladi, boshqa haydovchilar uchun mos keladigan mustaqil kengaytma paketlarini tekshiring: -| Driver | Link | -| ------ | ---------------------------------------------------------------------------------------------------- | -| Redis | [https://github.com/goravel/redis](https://github.com/goravel/redis) | +| Haydovchi | Havola | +| --------- | ---------------------------------------------------------------------------------------------------- | +| Redis | [https://github.com/goravel/redis](https://github.com/goravel/redis) | -## Configuration +## Konfiguratsiya -Make all custom configurations in `config/cache.go`. +Barcha maxsus konfiguratsiyalarni `config/cache.go` faylida bajarishingiz kerak. -## Cache Usage +## Keshdan foydalanish -### Inject Context +### Kontekstni kiritish ```go facades.Cache().WithContext(ctx) ``` -### Accessing Multiple Cache Stores +### Bir nechta keshlash do'konlariga kirish -You may access various cache stores via the `Store` method. The key passed to the `Store` method should correspond to one of the stores listed in the "stores" configuration array in your cache configuration file: +Siz `Store` usuli orqali turli xil keshe do'konlariga kirishingiz mumkin. `Store` usuliga o‘tkazilgan kalit sizning keshlash konfiguratsiya faylingizdagi "stores" konfiguratsiya massivida ko‘rsatilgan do‘konlardan biriga mos kelishi kerak: ```go value := facades.Cache().Store("redis").Get("foo") ``` -### Retrieving Items From The Cache +### Keshdan elementlarni olish ```go value := facades.Cache().Get("goravel", "default") @@ -39,7 +39,7 @@ value := facades.Cache().GetInt("goravel", 1) value := facades.Cache().GetString("goravel", "default") ``` -You can pass a `func` as the default value. If the specified data does not exist in the cache, the result of `func` will be returned. The transitive closure method allows you to obtain default values from the database or other external services. Note the closure structure `func() any`. +Siz standart qiymat sifatida `func` ni o'tkazishingiz mumkin. Agar ko'rsatilgan ma'lumotlar keshdagi mavjud bo'lmasa, `func` natijasi qaytariladi. Tranzitiv yopish usuli sizga ma'lumotlar bazasidan yoki boshqa tashqi xizmatlardan standart qiymatlarni olish imkonini beradi. `func() any` yopish tuzilishini esda tuting. ```go value := facades.Cache().Get("goravel", func() any { @@ -47,15 +47,15 @@ value := facades.Cache().Get("goravel", func() any { }) ``` -### Checking For Item Existence +### Element Mavjudligini Tekshirish ```go bool := facades.Cache().Has("goravel") ``` -### Incrementing / Decrementing Values +### Qiymatlarni oshirish / kamaytirish -The `Increment` and `Decrement` methods may be used to adjust the value of integer items in the cache. Both methods accept an optional second argument indicating the amount by which to increment or decrement the item's value: +`Increment` va `Decrement` metodlari keshdagi butun sonli elementlarning qiymatini sozlash uchun ishlatilishi mumkin. Ikkala usul ham elementning qiymatini oshirish yoki kamaytirish miqdorini ko'rsatuvchi ixtiyoriy ikkinchi argumentni qabul qiladi: ```go facades.Cache().Increment("key") @@ -64,9 +64,9 @@ facades.Cache().Decrement("key") facades.Cache().Decrement("key", amount) ``` -### Retrieve & Store +### Olish va Saqlash -Sometimes you may want to get data from the cache, and when the requested cache item does not exist, the program can store a default value for you. +Ba'zan siz keshdan ma'lumot olishni xohlashingiz mumkin va so'ralgan kesh elementi mavjud bo'lmaganda, dastur siz uchun standart qiymatni saqlashi mumkin. ```go value, err := facades.Cache().Remember("goravel", 5*time.Second, func() (any, error) { @@ -74,9 +74,9 @@ value, err := facades.Cache().Remember("goravel", 5*time.Second, func() (any, er }) ``` -If the data you want does not exist in the cache, the closure passed to the `Remember` method will be executed, and then the result will be returned and placed in the cache. +Agar siz izlayotgan ma'lumot keshda mavjud bo'lmasa, `Remember` metodiga o'tkazilgan yopilish funktsiyasi bajariladi, so'ngra natija qaytariladi va keshga joylanadi. -You can use the `RememberForever` method to retrieve data from the cache or store it permanently: +Siz ma'lumotlarni keshdan olish yoki uni doimiy saqlash uchun `RememberForever` usulidan foydalanishingiz mumkin: ```go value, err := facades.Cache().RememberForever("goravel", func() (any, error) { @@ -84,106 +84,106 @@ value, err := facades.Cache().RememberForever("goravel", func() (any, error) { }) ``` -### Retrieve & Delete +### Olish va o‘chirish ```go -value := facades.Cache().Pull("goravel", "default") +qiymat := facades.Cache().Pull("goravel", "default") ``` -### Storing Items In The Cache +### Elementlarni keshdagi saqlash ```go err := facades.Cache().Put("goravel", "value", 5*time.Second) ``` -If the expiration time of the cache is set to `0`, the cache will be valid forever: +Agar keshing amal qilish muddati `0` ga o'rnatilgan bo'lsa, kesh abadiy amal qiladi: ```go err := facades.Cache().Put("goravel", "value", 0) ``` -### Store If Not Present +### Agar mavjud bo‘lmasa, saqlash -The `Add` method stores data only if it's not in the cache. It returns `true` if storage is successful and `false` if it's not. +`Add` usuli ma'lumotni faqat keshda bo'lmaganda saqlaydi. Agar saqlash muvaffaqiyatli bo'lsa, `true` qaytaradi, aks holda `false` qaytaradi. ```go -bool := facades.Cache().Add("goravel", "value", 5*time.Second) +bool := facades.Cache().Add("goravel", "qiymat", 5*time.Second) ``` -### Storing Items Forever +### Elementlarni Abadiy Saqlash -The `Forever` method can be used to store data persistently in the cache. Because these data will not expire, they must be manually deleted from the cache through the `Forget` method: +`Forever` usuli ma'lumotlarni keshda doimiy saqlash uchun ishlatilishi mumkin. Bu ma'lumotlar muddati tugamaydiganligi sababli, ular keshdan `Forget` metodi orqali qo'lda o'chirilishi kerak: ```go -bool := facades.Cache().Forever("goravel", "value") +bool := facades.Cache().Forever("goravel", "qiymat") ``` -### Removing Items From The Cache +### Keshdan elementlarni olib tashlash ```go bool := facades.Cache().Forget("goravel") ``` -You can use the `Flush` method to clear all caches: +Siz barcha keshlarni tozalash uchun `Flush` usulidan foydalanishingiz mumkin: ```go bool := facades.Cache().Flush() ``` -## Atomic Locks +## Atomik qulf -### Managing Locks +### Qulf boshqarish -Atomic locks allow for the manipulation of distributed locks without worrying about race conditions. You may create and manage locks using the `Lock` method: +Atomik qulfar raqobat sharoitlaridan xavotir olmasdan tarqatilgan qulfarni boshqarish imkonini beradi. Siz `Lock` usuli yordamida qulf yaratishingiz va boshqarishingiz mumkin: ```go lock := facades.Cache().Lock("foo", 10*time.Second) -if (lock.Get()) { - // Lock acquired for 10 seconds... +agar (lock.Get()) { + // 10 soniya uchun qulf olindi... lock.Release() } ``` -The `Get` method also accepts a closure. After the closure is executed, Goravel will automatically release the lock: +`Get` usuli shuningdek, yopilishni qabul qiladi. Yopilish bajarilgandan so'ng, Goravel avtomatik ravishda qulfni bo'shatadi: ```go facades.Cache().Lock("foo").Get(func () { - // Lock acquired for 10 seconds and automatically released... + // Qulf 10 soniya davomida olingan va avtomatik ravishda ozod qilingan... }); ``` -If the lock is not available at the moment you request it, you may instruct Goravel to wait for a specified number of seconds. If the lock can not be acquired within the specified time limit, will return `false`: +Agar siz so‘ragan vaqtda qulf mavjud bo‘lmasa, Goravelga ma’lum sonli soniya kutishni buyurishingiz mumkin. Agar belgilangan vaqt oralig'ida qulfni olish mumkin bo'lmasa, `false` qaytariladi: ```go lock := facades.Cache().Lock("foo", 10*time.Second) -// Lock acquired after waiting a maximum of 5 seconds... +// 5 soniya maksimal kutishdan so'ng qulf olingan... if (lock.Block(5*time.Second)) { lock.Release() } ``` -The example above may be simplified by passing a closure to the `Block` method. When a closure is passed to this method, Goravel will attempt to acquire the lock for the specified number of seconds and will automatically release the lock once the closure has been executed: +Yuqoridagi misol `Block` metodiga yopilishni uzatish orqali soddalashtirilishi mumkin. Ushbu usulga yopilish berilganda, Goravel belgilangan soniyalar davomida qulfni olishga harakat qiladi va yopilish bajarilgandan so'ng qulfni avtomatik ravishda bo'shatadi: ```go facades.Cache().Lock("foo", 10*time.Second).Block(5*time.Second, func () { - // Lock acquired after waiting a maximum of 5 seconds... + // 5 soniya maksimal kutishdan so'ng qulf olindi... }) ``` -If you would like to release a lock without respecting its current owner, you may use the `ForceRelease` method: +Agar siz qulfni uning hozirgi egasiga hurmat qilmasdan bo'shatmoqchi bo'lsangiz, `ForceRelease` usulidan foydalanishingiz mumkin: ```go facades.Cache().Lock("processing").ForceRelease(); ``` -## Adding Custom Cache Drivers +## Maxsus keshlash haydovchilarini qo'shish -### Configuration +### Konfiguratsiya -If you want to define a completely custom driver, you can specify the `custom` driver type in the `config/cache.go` configuration file. -Then include a `via` option to implement a `framework/contracts/cache/Driver` interface: +Agar siz to'liq maxsus haydovchi aniqlashni istasangiz, `config/cache.go` konfiguratsiya faylida `custom` haydovchi turini ko'rsatishingiz mumkin. +Keyin `framework/contracts/cache/Driver` interfeysini amalga oshirish uchun `via` opsiyasini qo'shing: ```go //config/cache.go @@ -198,9 +198,9 @@ Then include a `via` option to implement a `framework/contracts/cache/Driver` in }, ``` -### Implement Custom Driver +### Maxsus haydovchini amalga oshirish -Implement the `framework/contracts/cache/Driver` interface, files can be stored in the `app/extensions` folder (modifiable). +`framework/contracts/cache/Driver` interfeysini amalga oshiring, fayllar `app/extensions` papkasida saqlanishi mumkin (o'zgartirish mumkin). ```go // framework/contracts/cache/Driver From 0e2bfac3277c26ac35703202e6ea104b82217b6d Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Wed, 1 Apr 2026 18:53:08 +0800 Subject: [PATCH 090/163] New translations color.md (Uzbek) [skip ci] Update translations (Uzbek) color.md --- uz_UZ/digging-deeper/color.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/uz_UZ/digging-deeper/color.md b/uz_UZ/digging-deeper/color.md index b048ea7c7..14ac1beee 100644 --- a/uz_UZ/digging-deeper/color.md +++ b/uz_UZ/digging-deeper/color.md @@ -1,14 +1,14 @@ -# Color +# Rang [[toc]] -## Introduction +## Kirish -The `color` package provides a set of functions to colorize the output of the terminal using [PTerm](https://github.com/pterm/pterm) library. +`color` paketi [PTerm](https://github.com/pterm/pterm) kutubxonasi yordamida terminal chiqishini ranglash uchun funksiyalar to'plamini taqdim etadi. -## Specific Color +## Maxsus Rang -The package provides methods to create printers for specific colors. These methods allow you to easily colorize terminal output. +Paket ma'lum ranglar uchun printerlar yaratish usullarini taqdim etadi. Ushbu usullar terminal chiqishini oson rang berish imkonini beradi. - `color.Red()` - `color.Green()` @@ -21,29 +21,29 @@ The package provides methods to create printers for specific colors. These metho - `color.Gray()` - `color.Default()` -### Printer Methods +### Printer Usullari -A `contracts/support.Printer` provides the following methods to print or format text with color: +`contracts/support.Printer` rangli matnni chop etish yoki formatlash uchun quyidagi usullarni taqdim etadi: -- `Print` - Print text -- `Println` - Print text with a new line -- `Printf` - Print formatted text -- `Sprint` - Return colored text -- `Sprintln` - Return colored text with a new line -- `Sprintf` - Return formatted colored text +- `Print` - Matnni chop etish +- `Println` - Matnni yangi qator bilan chop etish +- `Printf` - Formatlangan matnni chop qilish +- `Sprint` - Rangli matnni qaytarish +- `Sprintln` - Yangi qator bilan rangli matn qaytaradi +- `Sprintf` - Formatlangan rangli matnni qaytarish ```go import "github.com/goravel/framework/support/color" -color.Blue().Println("Hello, Goravel!") -color.Green().Printf("Hello, %s!", "Goravel") +color.Blue().Println("Salom, Goravel!") +color.Green().Printf("Salom, %s!", "Goravel") ``` -## Custom Color +## Maxsus Rang ### `color.New` -The `color.New` function creates a new color printer. You can use this object to colorize the output of the terminal. +`color.New` funksiyasi yangi rang printerini yaratadi. Siz terminal chiqishini ranglash uchun ushbu ob'ektdan foydalanishingiz mumkin. ```go import "github.com/goravel/framework/support/color" From 60d7c47f0cfac3585bcafa24447c97fdd5f47361 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Wed, 1 Apr 2026 18:53:09 +0800 Subject: [PATCH 091/163] New translations event.md (Uzbek) [skip ci] Update translations (Uzbek) event.md --- uz_UZ/digging-deeper/event.md | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/uz_UZ/digging-deeper/event.md b/uz_UZ/digging-deeper/event.md index 35ba3f365..320cf579e 100644 --- a/uz_UZ/digging-deeper/event.md +++ b/uz_UZ/digging-deeper/event.md @@ -1,16 +1,16 @@ -# Events +# Tadbirlar [[toc]] -## Introduction +## Kirish -Goravel's events provide a simple observer pattern implementation, allowing you to subscribe and listen to various events that occur within your application. Event classes are typically stored in the `app/events` directory, while their listeners are stored in `app/listeners`. Don't worry if you don't see these directories in your application as they will be created for you as you generate events and listeners using Artisan console commands. +Goravel hodisalari oddiy kuzatuvchi naqshini amalga oshiradi, ilovangiz ichida sodir bo'ladigan turli xil hodisalarga obuna bo'lish va tinglash imkonini beradi. Tadbir sinflari odatda `app/events` katalogida saqlanadi, ularning tinglovchilari esa `app/listeners` katalogida saqlanadi. Agar ilovangizda bu kataloglarni ko'rmasangiz, xavotirlanmang, chunki ular siz Artisan konsol buyruqlari yordamida hodisalar va tinglovchilarni yaratayotganda siz uchun yaratiladi. -Events serve as a great way to decouple various aspects of your application, as a single event can have multiple listeners that do not depend on each other. For example, you may wish to send a Slack notification to your user each time an order is shipped. Instead of coupling your order processing code to your Slack notification code, you can raise an `app/events/OrderShipped` event which a listener can receive and use to dispatch a Slack notification. +Tadbirlar ilovangizning turli jihatlarini ajratish uchun ajoyib usul bo'lib xizmat qiladi, chunki bitta tadbir bir-biriga bog'liq bo'lmagan bir nechta tinglovchilarga ega bo'lishi mumkin. Masalan, har safar buyurtma jo'natilganda foydalanuvchingizga Slack bildirishnomasini yuborishni xohlashingiz mumkin. Buyurtmani qayta ishlash kodini Slack bildirishnomalari kodingiz bilan bog'lamasdan, siz `app/events/OrderShipped` hodisasini yaratishingiz mumkin, bu esa tinglovchi tomonidan qabul qilinib, Slack bildirishnomasini yuborish uchun ishlatilishi mumkin. -## Register Events & Listeners +## Tadbirlar va tinglovchilarni ro'yxatdan o'tkazish -All events and listeners should be registered via the `WithEvents` function in the `bootstrap/app.go` file: +Barcha hodisalar va tinglovchilar `bootstrap/app.go` faylidagi `WithEvents` funksiyasi orqali ro'yxatdan o'tkazilishi kerak: ```go func Boot() contractsfoundation.Application { @@ -27,9 +27,9 @@ func Boot() contractsfoundation.Application { } ``` -### Generating Events & Listeners +### Voqealarni va Tinglovchilarni Yaratish -You can use the `make:event` and `make:listener` Artisan commands to generate individual events and listeners: +Siz `make:event` va `make:listener` Artisan buyruqlaridan foydalanib, alohida hodisalar va tinglovchilarni yaratishingiz mumkin: ```go ./artisan make:event PodcastProcessed @@ -39,9 +39,9 @@ You can use the `make:event` and `make:listener` Artisan commands to generate in ./artisan make:listener user/SendPodcastNotification ``` -## Defining Events +## Tadbirlarni aniqlash -An event class is essentially a data container that holds the information related to the event, the `Handle` method of `event` passes in and returns the `[]event.Arg` structure, which can be used to process data. The processed data will then be passed on to all associated `listeners`. For example, let's assume an `app\events\OrderShipped` event: +Tadbir sinfi asosan tadbir bilan bog'liq ma'lumotlarni o'z ichiga olgan ma'lumotlar konteyneridir, `event` ning `Handle` usuli `[]event.Arg` tuzilmasini kiritadi va qaytaradi, bu ma'lumotlarni qayta ishlash uchun ishlatilishi mumkin. Qayta ishlangan ma'lumotlar keyin barcha bog'langan `listener`larga o'tkaziladi. Masalan, `app\events\OrderShipped` hodisasini faraz qilaylik: ```go package events @@ -55,9 +55,9 @@ func (receiver *OrderShipped) Handle(args []event.Arg) ([]event.Arg, error) { } ``` -## Defining Listeners +## Tinglovchilarni belgilash -Next, let's take a look at the listener for our example event. Event listeners receive `[]event.Arg` of the event `Handle` method returns. Within the `Handle` method, you may perform any actions necessary to respond to the event: +Keyingi, keling, bizning misol hodisasi uchun tinglovchini ko'rib chiqaylik. Tadbir tinglovchilari `Handle` usulining qaytaradigan `[]event.Arg` tadbirini oladi. `Handle` usulida siz hodisaga javob berish uchun zarur bo'lgan har qanday harakatlarni bajara olasiz: ```go package listeners @@ -85,13 +85,13 @@ func (receiver *SendShipmentNotification) Handle(args ...any) error { } ``` -### Stopping The Propagation Of An Event +### Tadbirning tarqalishini to'xtatish -Sometimes, you may wish to stop the propagation of an event to other listeners. You may do so by returning an error from your listener's `Handle` method. +Ba'zan, siz hodisaning boshqa tinglovchilarga tarqalishini to'xtatmoqchi bo'lishingiz mumkin. Buning uchun siz tinglovchingizning `Handle` usulidan xatoni qaytarishingiz mumkin. -## Queued Event Listeners +## Navbatga qo‘yilgan hodisa tinglovchilari -Queueing listeners can be beneficial if your listener is going to perform a slow task such as sending an email or making an HTTP request. Before using queued listeners, make sure to [configure your queue](queues.md) and start a queue worker on your server or local development environment. +Eshitingiz sekin vazifani bajaradigan bo'lsa, masalan, elektron pochta yuborish yoki HTTP so'rovini amalga oshirish kabi, navbatdagi tinglovchilar foydali bo'lishi mumkin. Navbatga qo‘yilgan tinglovchilardan foydalanishdan oldin, serveringizda yoki mahalliy ishlab chiqish muhitingizda [navbatni sozlang](queues.md) va navbat ishchisini ishga tushiring. ```go package listeners @@ -113,13 +113,13 @@ func (receiver *SendShipmentNotification) Handle(args ...any) error { } ``` -### Queued Event Listeners & Database Transactions +### Navbatga qo‘yilgan hodisa tinglovchilari va maʼlumotlar bazasi tranzaksiyalari -When queued listeners are dispatched within database transactions, the queue may process them before the database transaction has been committed. When this happens, any updates you have made to models or database records during the database transaction may not yet be reflected in the database. In addition, any models or database records created within the transaction may not exist in the database. If your listener depends on these models, unexpected errors can occur when the job that dispatches the queued listener is processed. At this time, the event needs to be placed outside the database transactions. +Navbatga qo‘yilgan tinglovchilar ma’lumotlar bazasi tranzaksiyalari ichida jo‘natilganda, navbat ularni ma’lumotlar bazasi tranzaksiyasi tasdiqlanmaganidan oldin qayta ishlashi mumkin. Bunday bo'lganda, ma'lumotlar bazasi tranzaksiyasi davomida modellar yoki ma'lumotlar bazasi yozuvlariga kiritgan yangilanishlaringiz ma'lumotlar bazasida hali aks ettirilmagan bo'lishi mumkin. Bundan tashqari, tranzaksiya ichida yaratilgan har qanday modellar yoki ma'lumotlar bazasi yozuvlari ma'lumotlar bazasida mavjud bo'lmasligi mumkin. Agar tinglovchingiz ushbu modellarga bog'liq bo'lsa, navbatdagi tinglovchini jo'natadigan ish qayta ishlanganda kutilmagan xatolar yuzaga kelishi mumkin. Bu vaqtda, tadbir ma'lumotlar bazasi tranzaksiyalaridan tashqarida joylashtirilishi kerak. -## Dispatching Events +## Vaqtinchalik hodisalar -We can dispatch Events by `facades.Event().Job().Dispatch()` method. +Biz hodisalarni `facades.Event().Job().Dispatch()` usuli orqali jo‘nata olamiz. ```go package controllers @@ -143,7 +143,7 @@ func (r UserController) Show(ctx http.Context) { } ``` -## `event.Arg.Type` Supported Types +## `event.Arg.Type` qo‘llab-quvvatlanadigan turlar ```go bool From 6c8b836cccc5f0ef139d41406bdf619cebbe238a Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Wed, 1 Apr 2026 18:53:11 +0800 Subject: [PATCH 092/163] New translations filesystem.md (Uzbek) [skip ci] Update translations (Uzbek) filesystem.md --- uz_UZ/digging-deeper/filesystem.md | 160 ++++++++++++++--------------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/uz_UZ/digging-deeper/filesystem.md b/uz_UZ/digging-deeper/filesystem.md index a8dce3f32..8449eb645 100644 --- a/uz_UZ/digging-deeper/filesystem.md +++ b/uz_UZ/digging-deeper/filesystem.md @@ -1,69 +1,69 @@ -# File Storage +# Fayl saqlash [[toc]] -## Introduction +## Kirish -The Goravel provides simple drivers for working with local filesystems, Amazon S3, Aliyun OSS, Tencent COS, Minio and Cloudinary. Even better, switching between these storage options between your local development machine and production server is amazingly simple as the API remains the same for each system. Goravel comes with a `local` driver, for other drivers, please check the corresponding independent extension package: +Goravel mahalliy fayl tizimlari, Amazon S3, Aliyun OSS, Tencent COS, Minio va Cloudinary bilan ishlash uchun oddiy drayverlarni taqdim etadi. Yanada yaxshisi, ushbu saqlash variantlari o'rtasida mahalliy ishlab chiqish mashinangiz va ishlab chiqarish serveringiz o'rtasida o'tish juda oddiy, chunki har bir tizim uchun API bir xil bo'lib qoladi. Goravel `local` haydovchi bilan birga keladi, boshqa haydovchilar uchun iltimos, tegishli mustaqil kengaytma paketini tekshiring: -| Driver | Link | -| ------ | ---------------------------------------------------------------------------------------------------- | -| S3 | [https://github.com/goravel/s3](https://github.com/goravel/s3) | -| OSS | [https://github.com/goravel/oss](https://github.com/goravel/oss) | -| COS | [https://github.com/goravel/cos](https://github.com/goravel/cos) | -| Minio | [https://github.com/goravel/minio](https://github.com/goravel/minio) | +| Haydovchi | Havola | +| ----------- | ---------------------------------------------------------------------------------------------------- | +| S3 | [https://github.com/goravel/s3](https://github.com/goravel/s3) | +| OSS | [https://github.com/goravel/oss](https://github.com/goravel/oss) | +| Tencent COS | [https://github.com/goravel/cos](https://github.com/goravel/cos) | +| Minio | [https://github.com/goravel/minio](https://github.com/goravel/minio) | -## Configuration +## Konfiguratsiya -Goravel's filesystem configuration file is located at `config/filesystems.go`. Within this file, you may configure all of your filesystem "disks", each disk represents a particular storage driver and storage location. +Goravelning fayl tizimi konfiguratsiya fayli `config/filesystems.go` manzilida joylashgan. Ushbu fayl ichida siz barcha fayl tizimi "disk"laringizni sozlashingiz mumkin, har bir disk ma'lum bir saqlash haydovchisi va saqlash joyini ifodalaydi. -> You may configure as many disks as you like and may even have multiple disks that use the same driver. +> Siz istagancha diskni sozlashingiz mumkin va hatto bir xil haydovchidan foydalanadigan bir nechta disklarga ham ega bo'lishingiz mumkin. -### The Local Driver +### Mahalliy haydovchi -When using the `local` driver, all file operations are relative to the `root` directory defined in your `filesystems` configuration file. By default, this value is set to the `storage/app` directory. Therefore, the following method would write to `storage/app/example.txt`: +`local` haydovchidan foydalanganda, barcha fayl operatsiyalari `filesystems` konfiguratsiya faylingizda belgilangan `root` katalogiga nisbatan amalga oshiriladi. Standart bo'yicha, bu qiymat `storage/app` katalogiga o'rnatilgan. Shuning uchun, quyidagi usul `storage/app/example.txt` fayliga yozadi: ```go -facades.Storage().Put("example.txt", "Contents") +facades.Storage().Put("example.txt", "Tarkib") ``` -### The Public Disk +### Ommaviy disk -The `public`` disk included in your application's `filesystems`configuration file is intended for files that are going to be publicly accessible. By default, the`public`disk uses the`local`driver and stores its files in`storage/app/public\`. If you want to visit these file from web, you can create a file routing: +Ilovangizning `filesystems` konfiguratsiya faylida kiritilgan `public` disk umumiy kirish uchun mo'ljallangan fayllar uchun mo'ljallangan. Standart sozlamalar bo'yicha, `public` disk `local` haydovchidan foydalanadi va fayllarini `storage/app/public` papkasida saqlaydi. Agar siz ushbu fayllarga veb orqali tashrif buyurmoqchi bo'lsangiz, fayl marshrutlash yaratishingiz mumkin: ```go -facades.Route().Static("storage", "./storage/app/public") +fasadlar.Route().Static("storage", "./storage/app/public") ``` -## Obtaining Disk Instances +## Disk namunalarini olish -The `Storage` facade may be used to interact with any of your configured disks. For example, you may use the `Put` method on the facade to store an avatar on the default disk. If you call methods on the `Storage` facade without first calling the `Disk` method, the method will automatically be passed to the default disk: +`Storage` fasadasi konfiguratsiya qilingan har qanday disklar bilan o'zaro aloqada foydalanish uchun ishlatilishi mumkin. Masalan, siz fasad ustida `Put` usulidan foydalanib, avatar standart diskda saqlashingiz mumkin. Agar siz `Disk` metodini chaqirmasdan `Storage` fasadida metodlarni chaqirsangiz, metod avtomatik ravishda standart diskka o'tkaziladi: ```go -facades.Storage().Put("avatars/1.png", "Contents") +facades.Storage().Put("avatars/1.png", "Kontent") ``` -If your application interacts with multiple disks, you may use the `Disk` method on the `Storage` facade to work with files on a particular disk: +Agar ilovangiz bir nechta disk bilan ishlasa, ma'lum bir diskdagi fayllar bilan ishlash uchun `Storage` fasadidagi `Disk` metodidan foydalanishingiz mumkin: ```go facades.Storage().Disk("s3").Put("avatars/1.png", "Contents") ``` -## Inject Context +## Kontekstni kiritish ```go facades.Storage().WithContext(ctx).Put("avatars/1.png", "Contents") ``` -## Retrieving Files +## Fayllarni olish -The `Get` method may be used to retrieve the contents of a file. The raw string contents of the file will be returned by the method. Remember, all file paths should be specified relative to the disk's `root` location: +`Get` usuli fayl mazmunini olish uchun ishlatilishi mumkin. Faylning xom satr tarkibi usul tomonidan qaytariladi. Eslab qoling, barcha fayl yo'llari diskning `root` joylashuviga nisbatan ko'rsatilishi kerak: ```go content := facades.Storage().Get("file.jpg") ``` -The `Exists` method may be used to determine if a file exists on the disk: +`Exists` usuli diskda fayl mavjudligini aniqlash uchun ishlatilishi mumkin: ```go if (facades.Storage().Disk("s3").Exists("file.jpg")) { @@ -71,7 +71,7 @@ if (facades.Storage().Disk("s3").Exists("file.jpg")) { } ``` -The `Missing` method may be used to determine if a file is missing from the disk: +`Missing` usuli diskda fayl yo'qligini aniqlash uchun ishlatilishi mumkin: ```go if (facades.Storage().Disk("s3").Missing("file.jpg")) { @@ -79,19 +79,19 @@ if (facades.Storage().Disk("s3").Missing("file.jpg")) { } ``` -### File URLs +### Fayl URL manzillari -You may use the `Url` method to get the URL for a given file. If you are using the `local` driver, this will typically just prepend `/storage` to the given path and return a relative URL to the file. If you are using the `s3` driver, the fully qualified remote URL will be returned: +Siz berilgan fayl uchun URL olish uchun `Url` metodidan foydalanishingiz mumkin. Agar siz `local` haydovchisidan foydalanayotgan bo'lsangiz, bu odatda berilgan yo'lni `/storage` bilan boshlab, faylga nisbiy URLni qaytaradi. Agar siz `s3` haydovchisidan foydalanayotgan bo'lsangiz, to'liq masofaviy URL qaytariladi: ```go url := facades.Storage().Url("file.jpg") ``` -> When using the `local` driver, the return value of `Url` is not URL encoded. For this reason, we recommend always storing your files using names that will create valid URLs. +> `local` haydovchidan foydalanganda, `Url`ning qaytarilgan qiymati URL kodlanmagan. Shu sababdan, fayllaringizni haqiqiy URL'lar yaratadigan nomlar bilan saqlashni har doim tavsiya qilamiz. -#### Temporary URLs +#### Vaqtinchalik URL manzillar -Using the `TemporaryUrl` method, you may create temporary URLs to files stored using the Non-local driver. This method accepts a path and a `Time` instance specifying when the URL should expire: +`TemporaryUrl` usuli yordamida, Non-local haydovchi yordamida saqlangan fayllarga vaqtinchalik URL-lar yaratishingiz mumkin. Bu usul yo'l va URL qachon muddati tugashi kerakligini belgilaydigan `Time` misolini qabul qiladi: ```go url, err := facades.Storage().TemporaryUrl( @@ -99,30 +99,30 @@ url, err := facades.Storage().TemporaryUrl( ) ``` -### File Metadata +### Fayl Metadata -In addition to reading and writing files, Goravel can also provide information about the files themselves: +Fayllarni o'qish va yozishdan tashqari, Goravel fayllarning o'zlari haqida ma'lumot ham taqdim etishi mumkin: ```go size := facades.Storage().Size("file.jpg") ``` -The `LastModified` method returns the last modified time of the file: +`LastModified` usuli faylning oxirgi o'zgartirilgan vaqtini qaytaradi: ```go time, err := facades.Storage().LastModified("file.jpg") ``` -The MIME type of a given file may be obtained via the `MimeType` method: +Berilgan faylning MIME turi `MimeType` usuli orqali olinishi mumkin: ```go mime, err := facades.Storage().MimeType("file.jpg") ``` -Also can use the `NewFile` method: +Shuningdek, `NewFile` usulidan foydalanish mumkin: ```go -import "github.com/goravel/framework/filesystem" +"github.com/goravel/framework/filesystem" paketini import qiling file, err := filesystem.NewFile("./logo.png") size, err := file.Size() @@ -130,41 +130,41 @@ lastModified, err := file.LastModified() mime, err := file.MimeType() ``` -### File Paths +### Fayl yo'llari -To obtain the path for a specific file, you can utilize the `Path` method. When using the `local` driver, this will provide you with the relative path to the file. However, if you are using a driver like `s3`, the method will give you the file's relative path within the bucket: +Muayyan fayl uchun yo'lni olish uchun siz `Path` usulidan foydalanishingiz mumkin. `local` haydovchidan foydalanganda, bu sizga faylning nisbiy yoʻlini taqdim etadi. Biroq, agar siz `s3` kabi haydovchidan foydalanayotgan bo'lsangiz, usul sizga faylning bak ichidagi nisbiy yo'lini beradi: ```go path := facades.Storage().Path("file.jpg") ``` -## Storing Files +## Fayllarni saqlash -The `Put` method may be used to store file contents on a disk. Remember, all file paths should be specified relative to the "root" location configured for the disk: +`Put` usuli diskda fayl tarkibini saqlash uchun ishlatilishi mumkin. Esda tuting, barcha fayl yo'llari disk uchun sozlangan "root" joyiga nisbatan ko'rsatilishi kerak: ```go err := facades.Storage().Put("file.jpg", contents) ``` -You can also use `PutFile` and `PutFileAs` to save files directly on disk: +Shuningdek, fayllarni to'g'ridan-to'g'ri diskda saqlash uchun `PutFile` va `PutFileAs` dan foydalanishingiz mumkin: ```go import "github.com/goravel/framework/filesystem" -// Automatically generate a unique ID for filename... +// Fayl nomi uchun avtomatik ravishda noyob ID yaratish... file, err := filesystem.NewFile("./logo.png") path := facades.Storage().PutFile("photos", file) -// Manually specify a filename... +// Fayl nomini qo'lda belgilash... file, err := filesystem.NewFile("./logo.png") path := facades.Storage().PutFileAs("photos", file, "photo.jpg") ``` -There are a few important things to note about the `PutFile` method. Note that we only specified a directory name and not a filename. By default, the `PutFile` method will generate a unique ID to serve as the filename. The file's extension will be determined by examining the file's MIME type. The path to the file will be returned by the `PutFile` method so you can store the path, including the generated filename, in your database. +`PutFile` usuli haqida bir nechta muhim narsalarni esda tutish kerak. E'tibor bering, biz faqat katalog nomini ko'rsatdik, fayl nomini emas. Standart holatda, `PutFile` metodi fayl nomi sifatida xizmat qilish uchun noyob ID yaratadi. Fayl kengaytmasi faylning MIME turini tekshirish orqali aniqlanadi. Fayl yo'li `PutFile` usuli tomonidan qaytariladi, shuning uchun siz yo'lni, shu jumladan yaratilgan fayl nomini, ma'lumotlar bazangizda saqlashingiz mumkin. -### Copying & Moving Files +### Fayllarni nusxalash va ko'chirish -The `Copy` method may be used to copy an existing file to a new location on the disk, while the `Move` method may be used to rename or move an existing file to a new location: +`Copy` usuli mavjud faylni diskdagi yangi joyga nusxalash uchun ishlatilishi mumkin, `Move` usuli esa mavjud faylni qayta nomlash yoki yangi joyga ko'chirish uchun ishlatilishi mumkin: ```go err := facades.Storage().Copy("old/file.jpg", "new/file.jpg") @@ -172,20 +172,20 @@ err := facades.Storage().Copy("old/file.jpg", "new/file.jpg") err := facades.Storage().Move("old/file.jpg", "new/file.jpg") ``` -### File Uploads +### Fayl yuklashlar -In web applications, one of the most common use cases for storing files is storing user-uploaded files such as photos and documents. Goravel makes it very easy to store uploaded files using the `Store` method on an uploaded file instance. Call the `Store` method with the path at which you wish to store the uploaded file: +Veb-ilovalarda fayllarni saqlashning eng keng tarqalgan qo'llanilishlaridan biri foydalanuvchi tomonidan yuklangan fotosuratlar va hujjatlar kabi fayllarni saqlashdir. Goravel yuklangan fayl namunasida `Store` usulidan foydalanib, yuklangan fayllarni saqlashni juda oson qiladi. Yuklangan faylni saqlamoqchi bo'lgan yo'lingiz bilan `Store` metodini chaqiring: ```go func (r *UserController) Show(ctx http.Context) { - file, err := ctx.Request().File("avatar") - path, err := file.Store("avatars") + fayl, xato := ctx.Request().File("avatar") + yo'l, xato := fayl.Store("avatars") } ``` -There are a few important things to note about this example. Note that we only specified a directory name, not a filename. By default, the `Store` method will generate a unique ID to serve as the filename. The file's extension will be determined by examining the file's MIME type. The path to the file will be returned by the `Store` method so you can store the path, including the generated filename, in your database. +Ushbu misol haqida bir nechta muhim narsalarni esda tutish kerak. E'tibor bering, biz faqat katalog nomini ko'rsatdik, fayl nomini emas. Standart holatda, `Store` usuli fayl nomi sifatida xizmat qilish uchun noyob ID yaratadi. Fayl kengaytmasi faylning MIME turini tekshirish orqali aniqlanadi. Fayl yo'li `Store` usuli tomonidan qaytariladi, shuning uchun siz yo'lni, jumladan, yaratilgan fayl nomini, ma'lumotlar bazangizda saqlashingiz mumkin. -You may also call the `PutFile` method on the `Storage` facade to perform the same file storage operation as the example above: +Shuningdek, yuqoridagi misolda ko'rsatilgan fayl saqlash operatsiyasini bajarish uchun `Storage` fasadida `PutFile` metodini ham chaqirishingiz mumkin: ```go import "github.com/goravel/framework/filesystem" @@ -196,14 +196,14 @@ path := facades.Storage().PutFile("photos", file) ### Specifying A File Name -If you do not want a filename to be automatically assigned to your stored file, you may use the `StoreAs` method, which receives the path, the filename, and the (optional) disk as its arguments: +Agar saqlangan faylingizga avtomatik ravishda fayl nomi berilmasligini istasangiz, `StoreAs` metodidan foydalanishingiz mumkin, bu metod argument sifatida yo‘l, fayl nomi va (ixtiyoriy) diskni qabul qiladi: ```go file, err := ctx.Request().File("avatar") path, err := file.StoreAs("avatars", "name") ``` -You may also use the `PutFileAs` method on the Storage facade, which will perform the same file storage operation as the example above: +Shuningdek, siz Storage fasadidagi `PutFileAs` metodidan ham foydalanishingiz mumkin, bu yuqoridagi misoldagi kabi fayl saqlash operatsiyasini bajaradi: ```go import "github.com/goravel/framework/filesystem" @@ -212,11 +212,11 @@ file, err := filesystem.NewFile("./logo.png") path := facades.Storage().PutFileAs("photos", file, "name") ``` -> If the file name specified by `StoreAs` and `PutFileAs` doesn't have a suffix, the suffix is automatically added based on the MIME of the file; otherwise, the specified file name is used directly. +> Agar `StoreAs` va `PutFileAs` tomonidan belgilangan fayl nomida kengaytma bo'lmasa, faylning MIME turiga asoslanib kengaytma avtomatik ravishda qo'shiladi; aks holda, belgilangan fayl nomi to'g'ridan-to'g'ri ishlatiladi. -### Specifying A Disk +### Diskni belgilash -By default, this uploaded file's `Store` method will use your default disk. If you would like to specify another disk, please use the `Disk` method: +Standart holda, yuklangan ushbu faylning `Store` usuli sizning standart diskingizdan foydalanadi. Agar boshqa diskni belgilamoqchi bo'lsangiz, `Disk` metodidan foydalaning: ```go func (r *UserController) Show(ctx http.Context) { @@ -225,9 +225,9 @@ func (r *UserController) Show(ctx http.Context) { } ``` -### Other Uploaded File Information +### Boshqa yuklangan fayl ma'lumotlari -If you would like to get the original name and extension of the uploaded file, you may do so using the `GetClientOriginalName` and `GetClientOriginalExtension` methods: +Agar yuklangan faylning asl nomi va kengaytmasini olishni istasangiz, `GetClientOriginalName` va `GetClientOriginalExtension` usullaridan foydalanishingiz mumkin: ```go file, err := ctx.Request().File("avatar") @@ -236,69 +236,69 @@ name := file.GetClientOriginalName() extension := file.GetClientOriginalExtension() ``` -However, keep in mind that the `GetClientOriginalName` and `GetClientOriginalExtension` methods are considered unsafe, as the file name and extension may be tampered with by a malicious user. For this reason, you should typically prefer the `HashName` and `Extension` methods to get a name and an extension for the given file upload: +Biroq, `GetClientOriginalName` va `GetClientOriginalExtension` usullari xavfli hisoblanadi, chunki fayl nomi va kengaytmasi yomon niyatli foydalanuvchi tomonidan o'zgartirilishi mumkinligini yodda tuting. Shu sababli, berilgan fayl yuklash uchun nom va kengaytmani olish uchun odatda `HashName` va `Extension` usullarini afzal ko'rishingiz kerak: ```go file, err := ctx.Request().File("avatar") -name := file.HashName() // Generate a unique, random name... -extension, err := file.Extension() // Determine the file's extension based on the file's MIME type... +name := file.HashName() // Yagona, tasodifiy nom hosil qilish... +extension, err := file.Extension() // Faylning MIME turiga asoslanib, fayl kengaytmasini aniqlash... ``` -## Deleting Files +## Fayllarni o'chirish -The `Delete` method accepts a single filename or an array of files to delete: +`Delete` usuli bitta fayl nomini yoki o'chirish uchun fayllar massivini qabul qiladi: ```go err := facades.Storage().Delete("file.jpg") err := facades.Storage().Delete("file.jpg", "file2.jpg") ``` -If necessary, you may specify the disk that the file should be deleted from: +Agar kerak bo'lsa, fayl o'chirilishi kerak bo'lgan diskni belgilashingiz mumkin: ```go err := facades.Storage().Disk("s3").Delete("file.jpg") ``` -## Directories +## Kataloglar -### Get All Files Within A Directory +### Barcha Fayllarni Katalog Ichida Olish -The `Files` method returns a slice of all of the files in a given directory. If you would like to retrieve a list of all files within a given directory including all subdirectories, you may use the `AllFiles` method: +`Files` usuli berilgan katalogdagi barcha fayllarning kesmasini qaytaradi. Agar berilgan katalogdagi barcha fayllar ro'yxatini, shu jumladan barcha pastki kataloglarni olishni istasangiz, `AllFiles` metodidan foydalanishingiz mumkin: ```go files, err := facades.Storage().Disk("s3").Files("directory") files, err := facades.Storage().Disk("s3").AllFiles("directory") ``` -### Get All Directories Within A Directory +### Katalog Ichidagi Barcha Kataloglarni Oling -The `Directories` method returns a slice of all the directories within a given directory. Additionally, you may use the `AllDirectories` method to get a list of all directories within a given directory and all of its subdirectories: +`Directories` usuli berilgan katalog ichidagi barcha kataloglarning kesmasini qaytaradi. Bundan tashqari, siz berilgan katalogdagi barcha kataloglar va uning barcha pastki kataloglari ro'yxatini olish uchun `AllDirectories` usulidan foydalanishingiz mumkin: ```go directories, err := facades.Storage().Disk("s3").Directories("directory") directories, err := facades.Storage().Disk("s3").AllDirectories("directory") ``` -### Create A Directory +### Papka yaratish -The `MakeDirectory` method will create the given directory, including any needed subdirectories: +`MakeDirectory` usuli berilgan katalogni, shu jumladan zarur bo'lgan barcha ichki kataloglarni yaratadi: ```go err := facades.Storage().MakeDirectory(directory) ``` -### Delete A Directory +### Katalogni o'chirish -Finally, the `DeleteDirectory` method may be used to remove a directory and all of its files: +Nihoyat, `DeleteDirectory` usuli katalog va uning barcha fayllarini olib tashlash uchun ishlatilishi mumkin: ```go err := facades.Storage().DeleteDirectory(directory) ``` -## Custom Filesystems +## Maxsus Fayl Tizimlari -You can set the `custom` driver in the `config/filesystems.go` file. +Siz `custom` haydovchini `config/filesystems.go` faylida o'rnatishingiz mumkin. ```go "custom": map[string]any{ @@ -307,7 +307,7 @@ You can set the `custom` driver in the `config/filesystems.go` file. }, ``` -You need to implement the `github.com/goravel/framework/contracts/filesystem/Driver` interface in the `via` configuration item. +Siz `via` konfiguratsiya elementida `github.com/goravel/framework/contracts/filesystem/Driver` interfeysini amalga oshirishingiz kerak. ```go type Driver interface { @@ -337,4 +337,4 @@ type Driver interface { } ``` -> Note: Since the configuration has not been loaded when the custom driver is registered, so please use `facades.Config().Env()` to obtain the configuration in the custom driver. +> Eslatma: Maxsus drayver ro'yxatdan o'tkazilganda konfiguratsiya yuklanmaganligi sababli, iltimos, maxsus drayverda konfiguratsiyani olish uchun `facades.Config().Env()` dan foydalaning. From a71cc0f436f9bde1e3155e35d563be9aaff01720 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Wed, 1 Apr 2026 18:53:12 +0800 Subject: [PATCH 093/163] New translations helpers.md (Uzbek) [skip ci] Update translations (Uzbek) helpers.md --- uz_UZ/digging-deeper/helpers.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/uz_UZ/digging-deeper/helpers.md b/uz_UZ/digging-deeper/helpers.md index 3dbe6c8fd..36f5486c0 100644 --- a/uz_UZ/digging-deeper/helpers.md +++ b/uz_UZ/digging-deeper/helpers.md @@ -1,10 +1,10 @@ -# Helpers +# Yordamchilar [[toc]] -## Available Methods +## Mavjud usullar -### Paths +### Yo'llar | | | | | -------------------------------------------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------- | @@ -12,7 +12,7 @@ | [path.Database()](#path-database) | [path.Storage()](#path-storage) | [path.Public()](#path-public) | | [path.Resource()](#path-resource) | | | -### Carbon +### Karbon | | | | | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | @@ -32,7 +32,7 @@ | -------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- | | [debug.Dump()](#debug-dump) | [debug.SDump()](#debug-sdump) | [debug.FDump()](#debug-fdump) | -### Maps +### Xaritalar | | | | | -------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- | @@ -41,14 +41,14 @@ | [maps.Only()](#maps-only) | [maps.Pull()](#maps-pull) | [maps.Set()](#maps-set) | | [maps.Where()](#maps-where) | | | -### Convert +### Konvertatsiya qilish | | | | | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | ---------------------------------------------------------------------------- | | [convert.Tap()](#convert-tap) | [convert.With()](#convert-with) | [convert.Transform()](#convert-transform) | | [convert.Default()](#convert-default) | [convert.Pointer()](#convert-pointer) | | -### Collect +### Olish | | | | | ---------------------------------------------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | @@ -59,7 +59,7 @@ | [collect.Split()](#collect-split) | [collect.Sum()](#collect-sum) | [collect.Unique()](#collect-unique) | | [collect.Values()](#collect-values) | | | -## Paths +## Yo'llar ```go import "github.com/goravel/framework/support/path" @@ -67,7 +67,7 @@ import "github.com/goravel/framework/support/path" ### `path.App()` -The `path.App()` function returns the absolute path to your application's app directory. You may also use the `path.App()` function to generate a path to a file relative to the application directory: +. You may also use the `path.App()` function to generate a path to a file relative to the application directory: ```go path := path.App() @@ -195,7 +195,7 @@ carbon.IsTestNow() ### `carbon.Parse()` -The `carbon.Parse()` function gets `Carbon` object by String: + ```go carbon.Parse("2020-08-05 13:14:15") From 6427f324d7c7ef85822b265c8f705a180c657b3d Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Thu, 2 Apr 2026 17:25:40 +0800 Subject: [PATCH 094/163] New translations strings.md (Uzbek) [skip ci] Update translations (Uzbek) strings.md --- uz_UZ/digging-deeper/strings.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/uz_UZ/digging-deeper/strings.md b/uz_UZ/digging-deeper/strings.md index 832da5e6d..41b5a8903 100644 --- a/uz_UZ/digging-deeper/strings.md +++ b/uz_UZ/digging-deeper/strings.md @@ -1,10 +1,10 @@ -# Strings +# Matnllar [[toc]] -## Introduction +## Kirish -Goravel provides a fluent string manipulation library that allows you to easily manipulate strings. Fluent Strings allows you to combine multiple string operations through method chaining, where most of the methods returns an instance of `support/str.String`, letting you chain additional methods. To get the final string value after applying the chained operations, you can call the `String` method, which returns the underlying `string` value. +Goravel sizga satrlarni osongina boshqarish imkonini beruvchi ravon satrlarni boshqarish kutubxonasini taqdim etadi. Ravon Strings sizga bir nechta satr operatsiyalarini usul zanjiri orqali birlashtirish imkonini beradi, bu yerda usullarning aksariyati qo'shimcha usullarni zanjirlash imkonini beruvchi `support/str.String` misolini qaytaradi. Zanjirli operatsiyalarni qo'llagandan so'ng, oxirgi satr qiymatini olish uchun siz asosiy "satr" qiymatini qaytaradigan "String" usulini chaqirishingiz mumkin. ```go import "github.com/goravel/framework/support/str" @@ -12,11 +12,11 @@ import "github.com/goravel/framework/support/str" str.Of(" Goravel ").Trim().Lower().UpperFirst().String() // "Goravel" ``` -## Available Methods +## Mavjud usullar ### `Of` -The `Of` method creates a new fluent string instance from a given string. +`Of` usuli berilgan satrdan yangi ravon satr namunasini yaratadi. ```go import "github.com/goravel/framework/support/str" From 42f787c9655948ed3b474466d23bce8c928d0218 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Fri, 3 Apr 2026 13:44:46 +0800 Subject: [PATCH 095/163] New translations helpers.md (Uzbek) [skip ci] Update translations (Uzbek) helpers.md --- uz_UZ/digging-deeper/helpers.md | 146 ++++++++++++++++---------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/uz_UZ/digging-deeper/helpers.md b/uz_UZ/digging-deeper/helpers.md index 36f5486c0..8f4d11021 100644 --- a/uz_UZ/digging-deeper/helpers.md +++ b/uz_UZ/digging-deeper/helpers.md @@ -48,7 +48,7 @@ | [convert.Tap()](#convert-tap) | [convert.With()](#convert-with) | [convert.Transform()](#convert-transform) | | [convert.Default()](#convert-default) | [convert.Pointer()](#convert-pointer) | | -### Olish +### Yig'ish | | | | | ---------------------------------------------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------ | @@ -67,7 +67,7 @@ import "github.com/goravel/framework/support/path" ### `path.App()` -. You may also use the `path.App()` function to generate a path to a file relative to the application directory: +`path.App()` funksiyasi ilovangizning ilova katalogiga mutlaq yo'lni qaytaradi. Ilova katalogiga nisbatan faylga yo'l yaratish uchun `path.App()` funksiyasidan ham foydalanishingiz mumkin: ```go path := path.App() @@ -76,7 +76,7 @@ path := path.App("http/controllers/controller.go") ### `path.Base()` -The `path.Base()` function returns the absolute path to your application's root directory. You may also use the `path.Base()` function to generate a path to a given file relative to the project root directory: +`path.Base()` funksiyasi ilovangizning asosiy katalogiga mutlaq yo'lni qaytaradi. Loyihaning asosiy katalogiga nisbatan berilgan faylga yo'l yaratish uchun `path.Base()` funksiyasidan ham foydalanishingiz mumkin: ```go path := path.Base() @@ -85,7 +85,7 @@ path := path.Base("vendor/bin") ### `path.Config()` -The `path.Config()` function returns the absolute path to your application's config directory. You may also use the `path.Config()` function to generate a path to a given file within the application's configuration directory: +`path.Config()` funksiyasi ilovangizning konfiguratsiya katalogiga mutlaq yo'lni qaytaradi. Ilova konfiguratsiya katalogida berilgan faylga yo'l yaratish uchun siz shuningdek, `path.Config()` funksiyasidan foydalanishingiz mumkin: ```go path := path.Config() @@ -94,7 +94,7 @@ path := path.Config("app.go") ### `path.Database()` -The `path.Database()` function returns the absolute path to your application's database directory. You may also use the `path.Database()` function to generate a path to a given file within the `database` directory: +`path.Database()` funksiyasi ilovangizning ma'lumotlar bazasi katalogiga mutlaq yo'lni qaytaradi. Shuningdek, `ma'lumotlar bazasi` katalogidagi berilgan faylga yo'l yaratish uchun `path.Database()` funksiyasidan foydalanishingiz mumkin: ```go path := path.Database() @@ -103,7 +103,7 @@ path := path.Database("factories/user_factory.go") ### `path.Storage()` -The `path.Storage()` function returns the absolute path to your application's storage directory. You may also use the `path.Storage()` function to generate a path to a given file within the `storage` directory: +`path.Storage()` funksiyasi ilovangizning saqlash katalogiga mutlaq yo'lni qaytaradi. Shuningdek, `storage` katalogidagi berilgan faylga yo'l yaratish uchun `path.Storage()` funksiyasidan foydalanishingiz mumkin: ```go path := path.Storage() @@ -112,7 +112,7 @@ path := path.Storage("app/file.txt") ### `path.Public()` -The `path.Public()` function returns the absolute path to your application's public directory. You may also use the `path.Public()` function to generate a path to a given file within the `public` directory: +`path.Public()` funksiyasi ilovangizning umumiy katalogiga mutlaq yo'lni qaytaradi. Shuningdek, siz `public` katalogidagi berilgan faylga yo'l yaratish uchun `path.Public()` funksiyasidan foydalanishingiz mumkin: ```go path := path.Public() @@ -121,7 +121,7 @@ path := path.Public("css/app.css") ### `path.Lang()` -The `path.Lang()` function returns the absolute path to the `lang` directory. You may also use the `path.Lang()` function to generate a path to a given file within the `lang` directory: +`path.Lang()` funksiyasi `lang` katalogiga mutlaq yo'lni qaytaradi. Shuningdek, `lang` katalogidagi berilgan faylga yo'l yaratish uchun `path.Lang()` funksiyasidan foydalanishingiz mumkin: ```go path := path.Lang() @@ -130,7 +130,7 @@ path := path.Lang("en.json") ### `path.Resource()` -The `path.Resource()` function returns the absolute path to the `resource` directory. You may also use the `path.Resource()` function to generate a path to a given file within the `resource` directory: +`path.Resource()` funksiyasi `resource` katalogiga mutlaq yo'lni qaytaradi. Shuningdek, `resource` katalogidagi berilgan faylga yo'l yaratish uchun `path.Resource()` funksiyasidan foydalanishingiz mumkin: ```go path := path.Resource() @@ -139,7 +139,7 @@ path := path.Resource("css/app.css") ## Carbon -The `carbon` module of Goravel is an expansion by [dromara/carbon](https://github.com/dromara/carbon), please refer to the official documentation for details. +Goravelning "uglerod" moduli [dromara/carbon] (https://github.com/dromara/carbon) tomonidan kengaytirilgan versiya bo'lib, batafsil ma'lumot uchun rasmiy hujjatlarga qarang. ```go import "github.com/goravel/framework/support/carbon" @@ -155,7 +155,7 @@ carbon.Now() ### `carbon.SetTimezone()` -The `carbon.SetTimezone()` function sets timezone: +`carbon.SetTimezone()` funksiyasi vaqt mintaqasini o'rnatadi: ```go carbon.SetTimezone(carbon.UTC) @@ -163,7 +163,7 @@ carbon.SetTimezone(carbon.UTC) ### `carbon.SetLocale()` -The `carbon.SetLocale()` function sets language locale, refer to [locales list](https://github.com/dromara/carbon/tree/master/lang) for all supported locales: +`carbon.SetLocale()` funksiyasi til tilini o'rnatadi, barcha qo'llab-quvvatlanadigan tillar uchun [locales list](https://github.com/dromara/carbon/tree/master/lang) ga qarang: ```go carbon.SetLocale("en") @@ -171,7 +171,7 @@ carbon.SetLocale("en") ### `carbon.SetTestNow()` -The `carbon.SetTestNow()` function sets the time to a test value: +`carbon.SetTestNow()` funksiyasi vaqtni sinov qiymatiga o'rnatadi: ```go carbon.SetTestNow(carbon.Now()) @@ -179,7 +179,7 @@ carbon.SetTestNow(carbon.Now()) ### `carbon.CleanTestNow()` -The `carbon.CleanTestNow()` function clears the test now Carbon object: +`carbon.CleanTestNow()` funksiyasi testni hozir tozalaydi. Carbon obyekti: ```go carbon.CleanTestNow() @@ -187,7 +187,7 @@ carbon.CleanTestNow() ### `carbon.IsTestNow()` -The `carbon.IsTestNow()` function determines whether the time is a test value: +`carbon.IsTestNow()` funksiyasi vaqtning sinov qiymati ekanligini aniqlaydi: ```go carbon.IsTestNow() @@ -195,7 +195,7 @@ carbon.IsTestNow() ### `carbon.Parse()` - +`carbon.Parse()` funksiyasi String orqali `Carbon` obyektini oladi: ```go carbon.Parse("2020-08-05 13:14:15") @@ -203,7 +203,7 @@ carbon.Parse("2020-08-05 13:14:15") ### `carbon.ParseByLayout()` -The `carbon.ParseByLayout()` function gets `Carbon` object by given value and layout: +`carbon.ParseByLayout()` funksiyasi berilgan qiymat va joylashuv bo'yicha `Carbon` obyektini oladi: ```go carbon.ParseByLayout("2020-08-05 13:14:15", carbon.DateTimeLayout) @@ -212,7 +212,7 @@ carbon.ParseByLayout("2020|08|05 13|14|15", []string{"2006|01|02 15|04|05", "200 ### `carbon.ParseByFormat()` -The `carbon.ParseByFormat()` function gets `Carbon` object by given value and format: +`carbon.ParseByFormat()` funksiyasi berilgan qiymat va format bo'yicha `Carbon` obyektini oladi: ```go carbon.ParseByFormat("2020-08-05 13:14:15", carbon.DateTimeFormat) @@ -221,7 +221,7 @@ carbon.ParseByFormat("2020|08|05 13|14|15", []string{"Y|m|d H|i|s", "y|m|d h|i|s ### `carbon.FromTimestamp()` -The `carbon.FromTimestamp()` function gets `Carbon` object by timestamp with second precision: +`carbon.FromTimestamp()` funksiyasi vaqt tamg'asi bo'yicha ikkinchi aniqlik bilan `Carbon` obyektini oladi: ```go carbon.FromTimestamp(1577836800) @@ -229,7 +229,7 @@ carbon.FromTimestamp(1577836800) ### `carbon.FromTimestampMilli()` -The `carbon.FromTimestampMilli()` function gets `Carbon` object by timestamp with millisecond precision: +`carbon.FromTimestampMilli()` funksiyasi `Carbon` obyektini vaqt tamg'asi orqali millisekund aniqligida oladi: ```go carbon.FromTimestampMilli(1649735755999) @@ -237,7 +237,7 @@ carbon.FromTimestampMilli(1649735755999) ### `carbon.FromTimestampMicro()` -The `carbon.FromTimestampMicro()` function gets `Carbon` object by timestamp with microsecond precision: +`carbon.FromTimestampMicro()` funksiyasi mikrosekund aniqlik bilan vaqt tamg'asi orqali `Carbon` obyektini oladi: ```go carbon.FromTimestampMicro(1649735755999999) @@ -245,7 +245,7 @@ carbon.FromTimestampMicro(1649735755999999) ### `carbon.FromTimestampNano()` -The `carbon.FromTimestampNano()` function gets `Carbon` object by timestamp with nanosecond precision: +`carbon.FromTimestampNano()` funksiyasi `Carbon` obyektini vaqt tamg'asi orqali nanosekund aniqlik bilan oladi: ```go carbon.FromTimestampNano(1649735755999999999) @@ -253,7 +253,7 @@ carbon.FromTimestampNano(1649735755999999999) ### `carbon.FromDateTime()` -The `carbon.FromDateTime()` function gets `Carbon` object by year, month, day, hour, minute, second: +`carbon.FromDateTime()` funksiyasi `Carbon` obyektini yil, oy, kun, soat, daqiqa, soniya bo'yicha oladi: ```go carbon.FromDateTime(2020, 1, 1, 0, 0, 0) @@ -261,7 +261,7 @@ carbon.FromDateTime(2020, 1, 1, 0, 0, 0) ### `carbon.FromDateTimeMilli()` -The `carbon.FromDateTimeMilli()` function gets `Carbon` object by year, month, day, hour, minute, second, millisecond: +`carbon.FromDateTimeMilli()` funksiyasi `Carbon` obyektini yil, oy, kun, soat, daqiqa, soniya, millisekund bo'yicha oladi: ```go carbon.FromDateTimeMilli(2020, 1, 1, 0, 0, 0, 999) @@ -269,7 +269,7 @@ carbon.FromDateTimeMilli(2020, 1, 1, 0, 0, 0, 999) ### `carbon.FromDateTimeMicro()` -The `carbon.FromDateTimeMicro()` function gets `Carbon` object by year, month, day, hour, minute, second, microsecond: +`carbon.FromDateTimeMicro()` funksiyasi `Carbon` obyektini yil, oy, kun, soat, daqiqa, soniya, mikrosekund bo'yicha oladi: ```go carbon.FromDateTimeMicro(2020, 1, 1, 0, 0, 0, 999999) @@ -277,7 +277,7 @@ carbon.FromDateTimeMicro(2020, 1, 1, 0, 0, 0, 999999) ### `carbon.FromDateTimeNano()` -The `carbon.FromDateTimeNano()` function gets `Carbon` object by year, month, day, hour, minute, second, nanosecond: +`carbon.FromDateTimeNano()` funksiyasi `Carbon` obyektini yil, oy, kun, soat, daqiqa, soniya, nanosekund bo'yicha oladi: ```go carbon.FromDateTimeNano(2020, 1, 1, 0, 0, 0, 999999999) @@ -285,7 +285,7 @@ carbon.FromDateTimeNano(2020, 1, 1, 0, 0, 0, 999999999) ### `carbon.FromDate()` -The `carbon.FromDate()` function gets `Carbon` object by year, month, day: +`carbon.FromDate()` funksiyasi `Carbon` obyektini yil, oy, kun bo'yicha oladi: ```go carbon.FromDate(2020, 1, 1) @@ -293,7 +293,7 @@ carbon.FromDate(2020, 1, 1) ### `carbon.FromDateMilli()` -The `carbon.FromDateMilli()` function gets `Carbon` object by year, month, day, millisecond: +`carbon.FromDateMilli()` funksiyasi `Carbon` obyektini yil, oy, kun, millisekund bo'yicha oladi: ```go carbon.FromDateMilli(2020, 1, 1, 999) @@ -301,7 +301,7 @@ carbon.FromDateMilli(2020, 1, 1, 999) ### `carbon.FromDateMicro()` -The `carbon.FromDateMicro()` function gets `Carbon` object by year, month, day, microsecond: +`carbon.FromDateMicro()` funksiyasi `Carbon` obyektini yil, oy, kun, mikrosekund bo'yicha oladi: ```go carbon.FromDateMicro(2020, 1, 1, 999999) @@ -309,7 +309,7 @@ carbon.FromDateMicro(2020, 1, 1, 999999) ### `carbon.FromDateNano()` -The `carbon.FromDateNano()` function gets `Carbon` object by year, month, day, nanosecond: +`carbon.FromDateNano()` funksiyasi `Carbon` obyektini yil, oy, kun, nanosekund bo'yicha oladi: ```go carbon.FromDateNano(2020, 1, 1, 999999999) @@ -317,7 +317,7 @@ carbon.FromDateNano(2020, 1, 1, 999999999) ### `carbon.FromTime()` -The `carbon.FromTime()` function gets `Carbon` object by hour, minute, second: +`carbon.FromTime()` funksiyasi `Carbon` obyektini soat, daqiqa, soniya bo'yicha oladi: ```go carbon.FromTime(13, 14, 15) @@ -325,7 +325,7 @@ carbon.FromTime(13, 14, 15) ### `carbon.FromTimeMilli()` -The `carbon.FromTimeMilli()` function gets `Carbon` object by hour, minute, second, millisecond: +`carbon.FromTimeMilli()` funksiyasi `Carbon` obyektini soat, daqiqa, soniya, millisekund bo'yicha oladi: ```go carbon.FromTimeMilli(13, 14, 15, 999) @@ -333,7 +333,7 @@ carbon.FromTimeMilli(13, 14, 15, 999) ### `carbon.FromTimeMicro()` -The `carbon.FromTimeMicro()` function gets `Carbon` object by hour, minute, second, microsecond: +`carbon.FromTimeMicro()` funksiyasi `Carbon` obyektini soat, daqiqa, soniya, mikrosekund bo'yicha oladi: ```go carbon.FromTimeMicro(13, 14, 15, 999999) @@ -341,7 +341,7 @@ carbon.FromTimeMicro(13, 14, 15, 999999) ### `carbon.FromTimeNano()` -The `carbon.FromTimeNano()` function gets `Carbon` object by hour, minute, second, nanosecond: +`carbon.FromTimeNano()` funksiyasi `Carbon` obyektini soat, daqiqa, soniya, nanosekund bo'yicha oladi: ```go carbon.FromTimeNano(13, 14, 15, 999999999) @@ -349,13 +349,13 @@ carbon.FromTimeNano(13, 14, 15, 999999999) ### `carbon.FromStdTime()` -The `carbon.FromStdTime()` function gets `Carbon` object by `time.Time`: +`carbon.FromStdTime()` funksiyasi `time.Time` orqali `Carbon` obyektini oladi: ```go carbon.FromStdTime(time.Now()) ``` -## Debug +## Nosozliklarni tuzatish ```go import "github.com/goravel/framework/support/debug" @@ -363,7 +363,7 @@ import "github.com/goravel/framework/support/debug" ### `debug.Dump()` -The `debug.Dump()` function prints any variable: +`debug.Dump()` funksiyasi istalgan o'zgaruvchini chop etadi: ```go debug.Dump(myVar1, myVar2, ...) @@ -371,7 +371,7 @@ debug.Dump(myVar1, myVar2, ...) ### `debug.FDump()` -The `debug.FDump()` function prints any variable to `io.Writer`: +`debug.FDump()` funksiyasi istalgan o'zgaruvchini `io.Writer` ga chop etadi: ```go debug.FDump(someWriter, myVar1, myVar2, ...) @@ -379,13 +379,13 @@ debug.FDump(someWriter, myVar1, myVar2, ...) ### `debug.SDump()` -The `debug.SDump()` function prints any variable to `string`: +`debug.SDump()` funksiyasi istalgan o'zgaruvchini `string` ga yozib chiqaradi: ```go debug.SDump(myVar1, myVar2, ...) ``` -## Maps +## Xaritalar ```go import "github.com/goravel/framework/support/maps" @@ -393,7 +393,7 @@ import "github.com/goravel/framework/support/maps" ### `maps.Add()` -The `maps.Add()` function adds a new key-value pair to the given map if the key does not already exist in the map: +Agar kalit xaritada mavjud bo'lmasa, `maps.Add()` funksiyasi berilgan xaritaga yangi kalit-qiymat juftligini qo'shadi: ```go mp := map[string]any{"name": "Krishan"} @@ -408,7 +408,7 @@ maps.Add(mp2, "name", "Krishan") ### `maps.Exists()` -The `maps.Exists()` function determines if the given key exists in the provided map: +`maps.Exists()` funksiyasi berilgan kalit berilgan xaritada mavjudligini aniqlaydi: ```go mp := map[string]any{"name": "Krishan", "age": 22} @@ -420,7 +420,7 @@ maps.Exists(mp, "email") // false ### `maps.Forget()` -The `maps.Forget()` function removes the given key(s) from the provided map: +`maps.Forget()` funksiyasi berilgan xaritadan berilgan kalit(lar)ni olib tashlaydi: ```go mp := map[string]string{"name": "Krishan", "age": "22"} @@ -431,7 +431,7 @@ maps.Forget(mp, "name", "age") ### `maps.Get()` -The `maps.Get()` function retrieves the value of the given key from the provided map. If the key does not exist, the default value will be returned: +`maps.Get()` funksiyasi berilgan xaritadan berilgan kalitning qiymatini oladi. Agar kalit mavjud bo'lmasa, standart qiymat qaytariladi: ```go mp := map[string]any{"name": "Bowen"} @@ -443,7 +443,7 @@ maps.Get(mp, "age", 22) // 22 ### `maps.Has()` -The `maps.Has()` function determines if the given key(s) exists in the provided map: +`maps.Has()` funksiyasi berilgan kalit(lar)ning berilgan xaritada mavjudligini aniqlaydi: ```go mp := map[string]any{"name": "Goravel", "language": "Go"} @@ -455,7 +455,7 @@ maps.Has(mp, "name", "age") // false ### `maps.HasAny()` -The `maps.HasAny()` function determines if any of the given key(s) exists in the provided map: +`maps.HasAny()` funksiyasi berilgan xaritada berilgan kalit(lar)ning birortasi mavjudligini aniqlaydi: ```go mp := map[string]any{"name": "Goravel", "language": "Go"} @@ -467,7 +467,7 @@ maps.HasAny(mp, "age", "email") // false ### `maps.Only()` -The `maps.Only()` function retrieves only the given key(s) from the provided map: +`maps.Only()` funksiyasi berilgan xaritadan faqat berilgan kalit(lar)ni oladi: ```go mp := map[string]any{"name": "Goravel", "language": "Go"} @@ -481,7 +481,7 @@ maps.Only(mp, "name", "age") ### `maps.Pull()` -The `maps.Pull()` function retrieves and removes the given key from the provided map: +`maps.Pull()` funksiyasi berilgan xaritadan berilgan kalitni oladi va olib tashlaydi: ```go mp := map[string]any{"name": "Goravel", "language": "Go"} @@ -490,7 +490,7 @@ maps.Pull(mp, "name") // map[string]any{"language": "Go"} ``` -A default value can be provided as the third argument to the `maps.Pull()` function. This value will be returned if the key does not exist in the map: +`maps.Pull()` funksiyasiga uchinchi argument sifatida standart qiymat berilishi mumkin. Agar kalit xaritada mavjud bo'lmasa, bu qiymat qaytariladi: ```go mp := map[string]any{"name": "Goravel", "language": "Go"} @@ -501,7 +501,7 @@ maps.Pull(mp, "age", "default") ### `maps.Set()` -The `maps.Set()` function sets the given key and value in the provided map: +`maps.Set()` funksiyasi berilgan xaritada berilgan kalit va qiymatni o'rnatadi: ```go mp := map[string]any{"name": "Goravel"} @@ -512,7 +512,7 @@ maps.Set(mp, "language", "Go") ### `maps.Where()` -The `maps.Where()` function filters the provided map using the given callback: +`maps.Where()` funksiyasi berilgan xaritani berilgan qayta chaqiruv yordamida filtrlaydi: ```go mp := map[string]string{"name": "Goravel", "language": "Go"} @@ -523,7 +523,7 @@ maps.Where(mp, func(key string, value string) bool { // map[string]string{"name": "Goravel"} ``` -## Convert +## Konvertatsiya qilish ```go import "github.com/goravel/framework/support/convert" @@ -531,7 +531,7 @@ import "github.com/goravel/framework/support/convert" ### `convert.Tap()` -The `convert.Tap()` function passes the given value to the provided callback and returns the value: +`convert.Tap()` funksiyasi berilgan qiymatni berilgan qayta chaqiruvga uzatadi va qiymatni qaytaradi: ```go convert.Tap("Goravel", func(value string) { @@ -548,7 +548,7 @@ convert.Tap(mp, func(value map[string]string) { ### `convert.Transform()` -The `convert.Transform()` transforms the given value using the provided callback and returns the result: +`convert.Transform()` berilgan qiymatni berilgan qayta chaqiruv yordamida o'zgartiradi va natijani qaytaradi: ```go convert.Transform(1, strconv.Itoa) @@ -562,7 +562,7 @@ convert.Transform("foo", func(s string) *foo { ### `convert.With()` -The `convert.With()` executes the given callback with the provided value and returns the result of the callback: +`convert.With()` berilgan qiymat bilan qaytariladigan chaqiruvni bajaradi va qaytariladigan chaqiruv natijasini qaytaradi: ```go convert.With("Goravel", func(value string) string { @@ -573,7 +573,7 @@ convert.With("Goravel", func(value string) string { ### `convert.Default()` -The `convert.Default()` method returns first non-zero value. If all values are zero, it returns zero value. +`convert.Default()` usuli birinchi nolga teng bo'lmagan qiymatni qaytaradi. Agar barcha qiymatlar nolga teng bo'lsa, u nol qiymatni qaytaradi. ```go convert.Default("", "foo") // foo @@ -585,7 +585,7 @@ convert.Default(0, 1) // 1 ### `convert.Pointer()` -The `convert.Pointer()` method returns the pointer of the given value. +`convert.Pointer()` usuli berilgan qiymatning ko'rsatkichini qaytaradi. ```go convert.Pointer("foo") // *string("foo") @@ -593,7 +593,7 @@ convert.Pointer("foo") // *string("foo") convert.Pointer(1) // *int(1) ``` -## Collect +## Yig'ish ```go import "github.com/goravel/framework/support/collect" @@ -601,7 +601,7 @@ import "github.com/goravel/framework/support/collect" ### `collect.Count()` -The `collect.Count()` function returns the number of items in the given collection: +`collect.Count()` funksiyasi berilgan to'plamdagi elementlar sonini qaytaradi: ```go collect.Count([]string{"Goravel", "Framework"}) // 2 @@ -609,7 +609,7 @@ collect.Count([]string{"Goravel", "Framework"}) // 2 ### `collect.CountBy()` -The `collect.CountBy()` function counts the occurrences for which the predicate is true: +`collect.CountBy()` funksiyasi predikat rost bo'lgan holatlarni hisoblaydi: ```go collect.CountBy([]string{"Goravel", "Framework"}, func(value string) bool { @@ -620,7 +620,7 @@ collect.CountBy([]string{"Goravel", "Framework"}, func(value string) bool { ### `collect.Each()` -The `collect.Each()` function iterates over the items in the given collection and passes each item to the given callback: +`collect.Each()` funksiyasi berilgan to'plamdagi elementlar ustida iteratsiya qiladi va har bir elementni berilgan qayta chaqiruvga o'tkazadi: ```go collect.Each([]string{"Goravel", "Framework"}, func(value string, index int) { @@ -632,7 +632,7 @@ collect.Each([]string{"Goravel", "Framework"}, func(value string, index int) { ### `collect.Filter()` -The `collect.Filter()` function filters the items in the collection using the given callback: +`collect.Filter()` funksiyasi berilgan qayta chaqiruv yordamida to'plamdagi elementlarni filtrlaydi: ```go collect.Filter([]string{"Goravel", "Framework"}, func(value string) bool { @@ -643,7 +643,7 @@ collect.Filter([]string{"Goravel", "Framework"}, func(value string) bool { ### `collect.GroupBy()` -The `collect.GroupBy()` function groups the items in the collection by the result of the given callback: +`collect.GroupBy()` funksiyasi berilgan qayta chaqiruv natijasi bo'yicha to'plamdagi elementlarni guruhlaydi: ```go // use example of complex map slice (use different example) @@ -662,7 +662,7 @@ collect.GroupBy([]map[string]string{ ### `collect.Keys()` -The `collect.Keys()` function returns all the keys for the items in the collection: +`collect.Keys()` funksiyasi to'plamdagi elementlar uchun barcha kalitlarni qaytaradi: ```go collect.Keys(map[string]string{"name": "Goravel", "language": "Go"}) @@ -671,7 +671,7 @@ collect.Keys(map[string]string{"name": "Goravel", "language": "Go"}) ### `collect.Map()` -The `collect.Map()` function converts one type of collection into another using the given iteratee: +`collect.Map()` funksiyasi berilgan iterate yordamida bir turdagi to'plamni boshqasiga o'zgartiradi: ```go collect.Map([]string{"Goravel", "Framework"}, func(value string, _ int) string { @@ -682,7 +682,7 @@ collect.Map([]string{"Goravel", "Framework"}, func(value string, _ int) string ### `collect.Max()` -The `collect.Max()` function returns the maximum value of the given collection: +`collect.Max()` funksiyasi berilgan to'plamning maksimal qiymatini qaytaradi: ```go collect.Max([]int{1, 2, 3, 4, 5}) // 5 @@ -690,7 +690,7 @@ collect.Max([]int{1, 2, 3, 4, 5}) // 5 ### `collect.Merge()` -The `collect.Merge()` function merges the given maps into a single map: +`collect.Merge()` funksiyasi berilgan xaritalarni bitta xaritaga birlashtiradi: ```go collect.Merge(map[string]string{"name": "Goravel"}, map[string]string{"language": "Go"}) @@ -702,7 +702,7 @@ collect.Merge(map[string]string{"name": "Goravel"}, map[string]string{"name": "F ### `collect.Min()` -The `collect.Min()` function returns the minimum value of the given collection: +`collect.Min()` funksiyasi berilgan to'plamning minimal qiymatini qaytaradi: ```go collect.Min([]int{1, 2, 3, 4, 5}) // 1 @@ -710,7 +710,7 @@ collect.Min([]int{1, 2, 3, 4, 5}) // 1 ### `collect.Reverse()` -The `collect.Reverse()` function reverses the items in the collection: +`collect.Reverse()` funksiyasi to'plamdagi elementlarni teskari yo'naltiradi: ```go collect.Reverse([]string{"Goravel", "Framework"}) @@ -719,7 +719,7 @@ collect.Reverse([]string{"Goravel", "Framework"}) ### `collect.Shuffle()` -The `collect.Shuffle()` function shuffles the items in the collection: +`collect.Shuffle()` funksiyasi to'plamdagi elementlarni aralashtiradi: ```go collect.Shuffle([]int{1, 2, 3, 4, 5}) @@ -728,7 +728,7 @@ collect.Shuffle([]int{1, 2, 3, 4, 5}) ### `collect.Split()` -The `collect.Split()` function splits a collection into the groups of the given length. If the collection can't be split evenly, the final chunk will contain the remaining items: +`collect.Split()` funksiyasi to'plamni berilgan uzunlikdagi guruhlarga ajratadi. Agar to'plamni teng ravishda taqsimlab bo'lmasa, oxirgi qism qolgan elementlarni o'z ichiga oladi: ```go collect.Split([]int{1, 2, 3, 4, 5}, 2) @@ -745,7 +745,7 @@ collect.Sum([]int{1, 2, 3, 4, 5}) // 15 ### `collect.Unique()` -The `collect.Unique()` method returns the duplicate-free collection where in case of duplicate values, only the first occurrence will be kept: +`collect.Unique()` usuli takroriy qiymatlar bo'lsa, faqat birinchi holat saqlanib qoladigan takroriy to'plamni qaytaradi: ```go collect.Unique([]string{"Goravel", "Framework", "Goravel"}) @@ -754,7 +754,7 @@ collect.Unique([]string{"Goravel", "Framework", "Goravel"}) ### `collect.Values()` -The `collect.Values()` function returns all the values of the given collection: +`collect.Values()` funksiyasi berilgan to'plamning barcha qiymatlarini qaytaradi: ```go collect.Values(map[string]string{"name": "Goravel", "language": "Go"}) From 670ca52c1031ca786914fea531549a69333f9372 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Fri, 3 Apr 2026 15:00:36 +0800 Subject: [PATCH 096/163] New translations http-client.md (Uzbek) [skip ci] Update translations (Uzbek) http-client.md --- uz_UZ/digging-deeper/http-client.md | 286 +++++++++++++--------------- 1 file changed, 132 insertions(+), 154 deletions(-) diff --git a/uz_UZ/digging-deeper/http-client.md b/uz_UZ/digging-deeper/http-client.md index f36be17e9..6fe28a539 100644 --- a/uz_UZ/digging-deeper/http-client.md +++ b/uz_UZ/digging-deeper/http-client.md @@ -1,21 +1,19 @@ -# HTTP Client +# HTTP mijozi [[toc]] -## Introduction +## Kirish -In software development, there are many instances when you need to call an API to fetch data— -whether it's connecting to a microservice or accessing a third-party API. In such cases, -Goravel offers an easy-to-use, expressive, and minimalist API built on the standard `net/http` library, -all designed to enhance the developer experience. +Dasturiy ta'minotni ishlab chiqishda, ma'lumotlarni olish uchun API ni chaqirish kerak bo'lgan ko'p holatlar mavjud — xoh u mikroservisga ulanish bo'lsin, xoh uchinchi tomon API siga kirish bo'lsin. Bunday hollarda, +Goravel standart "net/http" kutubxonasida yaratilgan, foydalanish oson, ifodali va minimalist API-ni taklif qiladi, bularning barchasi ishlab chiquvchilar tajribasini yaxshilash uchun mo'ljallangan. -## Configuration +## Konfiguratsiya -Goravel's HTTP client is built on top of the `net/http.Client` for making HTTP requests. If you need to tweak its internal settings, just update the `clients` property in the `config/http.go` file. +Goravelning HTTP mijozi HTTP so'rovlarini amalga oshirish uchun `net/http.Client` ustiga qurilgan. Agar uning ichki sozlamalarini o'zgartirishingiz kerak bo'lsa, shunchaki `config/http.go` faylidagi `clients` xususiyatini yangilang. -## Making Requests +## So'rovlar berish -The Http facade provides a convenient way to make HTTP requests using familiar verbs: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`, and `OPTIONS`. +Http jabhasi tanish fe'llar yordamida HTTP so'rovlarini amalga oshirishning qulay usulini taqdim etadi: `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD` va \`OPTIONS. **Example: GET Request** @@ -23,59 +21,55 @@ The Http facade provides a convenient way to make HTTP requests using familiar v response, err := facades.Http().Get("https://example.com") ``` -Each HTTP verb method returns a `response` of type `framework/contracts/http/client.Response` and an `err` if the request fails. +Har bir HTTP fe'l usuli `framework/contracts/http/client.Response` turidagi `javob` va agar so'rov bajarilmasa, `err` qaytaradi. -You can use the `Client` function to specify which HTTP client configuration to use: +Qaysi HTTP mijoz konfiguratsiyasidan foydalanishni belgilash uchun `Client` funksiyasidan foydalanishingiz mumkin: ```go response, err := facades.Http().Client("github").Get("https://example.com") ``` -### Response Interface +### Javob interfeysi -The `framework/contracts/http/client.Response` interface provides the following methods to interact with the HTTP response: +`framework/contracts/http/client.Response` interfeysi HTTP javobi bilan o'zaro ishlashning quyidagi usullarini taqdim etadi: ```go type Response interface { - Bind(value any) error // Bind the response body to a struct - Body() (string, error) // Get the response body as a string - ClientError() bool // Check if the status code is in the 4xx range - Cookie(name string) *http.Cookie // Get a specific cookie - Cookies() []*http.Cookie // Get all response cookies - Failed() bool // Check if the status code is not in the 2xx range - Header(name string) string // Get the value of a specific header - Headers() http.Header // Get all response headers - Json() (map[string]any, error) // Decode the response body as JSON into a map - Redirect() bool // Check if the response is a redirect (3xx status code) - ServerError() bool // Check if the status code is in the 5xx range - Status() int // Get the HTTP status code - Successful() bool // Check if the status code is in the 2xx range - - /* status code related methods */ - - OK() bool // 200 OK - Created() bool // 201 Created - Accepted() bool // 202 Accepted - NoContent() bool // 204 No Content - MovedPermanently() bool // 301 Moved Permanently - Found() bool // 302 Found - BadRequest() bool // 400 Bad Request - Unauthorized() bool // 401 Unauthorized - PaymentRequired() bool // 402 Payment Required - Forbidden() bool // 403 Forbidden - NotFound() bool // 404 Not Found - RequestTimeout() bool // 408 Request Timeout - Conflict() bool // 409 Conflict - UnprocessableEntity() bool // 422 Unprocessable Entity - TooManyRequests() bool // 429 Too Many Requests +Bind(value any) xatosi // Javob tanasini strukturaga bog'lash +Body() (string, error) // Javob tanasini satr sifatida olish +ClientError() bool // Holat kodi 4xx oralig'ida ekanligini tekshirish +Cookie(name string) *http.Cookie // Muayyan cookie-faylni olish +Cookie() []*http.Cookie // Barcha javob cookie-fayllarini olish +Failed() bool // Holat kodi 2xx oralig'ida emasligini tekshirish +Header(name string) string // Muayyan sarlavhaning qiymatini olish +Header() http.Header // Barcha javob sarlavhalarini olish +Json() (map[string]any, error) // Javob tanasini JSON sifatida xaritaga dekodlash +Redirect() bool // Javob yo'naltirish ekanligini tekshirish (3xx holat kodi) +ServerError() bool // Holat kodi 5xx oralig'ida ekanligini tekshirish +Status() int // HTTP holat kodini olish +Successful() bool // Holat kodi 2xx oralig'ida ekanligini tekshirish + +/* holat kodi bilan bog'liq usullar */ + +OK() bool // 200 OK +Yaratilgan() bool // 201 Yaratilgan +Qabul qilingan() bool // 202 Qabul qilingan +Kontent yo'q() bool // 204 Kontent yo'q Ko'chirildi Doimiy() bool // 301 Doimiy ko'chirildi +Topildi() bool // 302 Topildi +NodRequest() bool // 400 Noto'g'ri so'rov Ruxsatsiz() bool // 401 Ruxsatsiz +To'lov talab qilinadi() bool // 402 To'lov talab qilinadi Taqiqlangan() bool // 403 Taqiqlangan +Topilmadi() bool // 404 Topilmadi +RequestTimeout() bool // 408 So'rov vaqti tugadi +Conflict() bool // 409 Conflict +UnprocessableEntity() bool // 422 Ishlov berilmaydigan obyekt TooManyRequests() bool // 429 Juda ko'p so'rovlar } ``` -### URI Templates +### URI shablonlari -URI Templates let you build dynamic request URLs using placeholders. -You can define these placeholders in your URL and then provide the values to replace them before making the request. -To achieve this, you can use `WithUrlParameter` for single parameters or `WithUrlParameters` for multiple parameters. +URI shablonlari sizga joy egallovchilaridan foydalanib, dinamik so'rov URL manzillarini yaratish imkonini beradi. +Siz ushbu joy egallovchilarni URL manzilingizda belgilashingiz va keyin so'rov yuborishdan oldin ularni almashtirish uchun qiymatlarni taqdim etishingiz mumkin. +Bunga erishish uchun siz bitta parametrlar uchun `WithUrlParameter` yoki bir nechta parametrlar uchun `WithUrlParameters` dan foydalanishingiz mumkin. ```go response, err := facades.Http(). @@ -92,10 +86,9 @@ response, err := facades.Http(). Get("https://api.example.com/books/{bookId}/chapters/{chapterNumber}") ``` -### Request Query Parameters +### So'rov parametrlarini so'rash -Add query parameters to your requests using `WithQueryParameter` for single parameters or -`WithQueryParameters` for multiple parameters via a map. +Bitta parametrlar uchun `WithQueryParameter` yoki xarita orqali bir nechta parametrlar uchun`WithQueryParameters` dan foydalanib, so'rovlaringizga so'rov parametrlarini qo'shing. ```go response1, err1 := facades.Http(). @@ -113,7 +106,7 @@ response2, err2 := facades.Http(). // Resulting URL: https://api.example.com/products?page=2&pageSize=10 ``` -You can also add query parameters directly as a formatted string using `WithQueryString`: +Shuningdek, so'rov parametrlarini to'g'ridan-to'g'ri formatlangan satr sifatida `WithQueryString` yordamida qo'shishingiz mumkin: ```go response, err := facades.Http(). @@ -121,10 +114,10 @@ response, err := facades.Http(). Get("https://api.example.com/items") ``` -### Sending a Request Body +### So'rov matnini yuborish -For HTTP verbs like `POST`, `PUT`, `PATCH` and `DELETE` accept `io.Reader` as the second argument. -To simplify building payloads, the framework provides utility methods for constructing request bodies. +`POST`, `PUT`, `PATCH` va `DELETE` kabi HTTP fe'llari uchun ikkinchi argument sifatida `io.Reader` ni qabul qiling. +Bino yuklamalarini soddalashtirish uchun tizim so'rov tanalarini qurish uchun foydali usullarni taqdim etadi. ```go import "github.com/goravel/framework/support/http" @@ -136,10 +129,9 @@ body, err := builder.Build() response, err := facades.Http().WithHeader("Content-Type", body.ContentType()).Post("https://example.com/users", body.Reader()) ``` -### Headers +### Sarlavhalar -You can add headers to your requests using `WithHeader` for a single header -or `WithHeaders` for multiple headers provided as a map. +Siz so'rovlaringizga bitta sarlavha uchun `WithHeader` yoki xarita sifatida taqdim etilgan bir nechta sarlavhalar uchun `WithHeaders` dan foydalanib sarlavhalar qo'shishingiz mumkin. ```go response, err := facades.Http(). @@ -155,7 +147,7 @@ response, err = facades.Http(). Get("https://api.example.com") ``` -You may use the `Accept` method to specify the content type that your application is expecting in response to your request: +So'rovingizga javoban ilovangiz kutayotgan kontent turini ko'rsatish uchun "Qabul qilish" usulidan foydalanishingiz mumkin: ```go response, err := facades.Http(). @@ -163,7 +155,7 @@ response, err := facades.Http(). Get("https://api.example.com") ``` -For convenience, you can use `AcceptJson` to quickly specify that you expect the API response to be in `application/json` format: +Qulaylik uchun, API javobi `application/json` formatida bo'lishini kutishingizni tezda belgilash uchun `AcceptJson` dan foydalanishingiz mumkin: ```go response, err := facades.Http(). @@ -171,7 +163,7 @@ response, err := facades.Http(). Get("https://api.example.com/data") ``` -To replace all existing headers with a new set, use `ReplaceHeaders`: +Mavjud sarlavhalarni yangi to'plam bilan almashtirish uchun "ReplaceHeaders" dan foydalaning: ```go response, err := facades.Http(). @@ -181,22 +173,22 @@ response, err := facades.Http(). Get("https://api.example.com") ``` -You can remove a specific header using `WithoutHeader` or clear all headers with `FlushHeaders`. +Siz "WithoutHeader" yordamida ma'lum bir sarlavhani olib tashlashingiz yoki "FlushHeaders" yordamida barcha sarlavhalarni tozalashingiz mumkin. ```go -response, err := facades.Http(). - WithoutHeader("X-Previous-Header"). - Get("https://api.example.com") - -// flush all headers -response, err := facades.Http(). - FlushHeaders(). - Get("https://api.example.com") +javob, xato := facades.Http(). +WithoutHeader("X-Previous-Header"). +Get("https://api.example.com") + +// barcha sarlavhalarni tozalash +javob, xato := facades.Http(). +FlushHeaders(). +Get("https://api.example.com") ``` -### Authentication +### Autentifikatsiya -You can specify basic authentication using the `WithBasicAuth` method: +Siz asosiy autentifikatsiyani `WithBasicAuth` usuli yordamida belgilashingiz mumkin: ```go response, err := facades.Http(). @@ -204,10 +196,9 @@ response, err := facades.Http(). Get("https://api.example.com/protected") ``` -#### Bearer Tokens +#### Bearer tokenlar -To quickly add a bearer token to the request's `Authorization` header, -you can use the `WithToken` method: +So'rovning "Avtorizatsiya" sarlavhasiga tashuvchi tokenni tezda qo'shish uchun siz "WithToken" usulidan foydalanishingiz mumkin: ```go response, err := facades.Http(). @@ -216,7 +207,7 @@ response, err := facades.Http(). ``` :::tip -The `WithToken` method also accepts an optional second argument to specify the token type (e.g., "Bearer", "Token"). +`WithToken` usuli shuningdek, token turini (masalan, "Bearer", "Token") belgilash uchun ixtiyoriy ikkinchi argumentni ham qabul qiladi. If no type is provided, it defaults to "Bearer". ```go @@ -227,7 +218,7 @@ response, err := facades.Http(). ::: -To remove the bearer token from the request, use the `WithoutToken` method: +So'rovdan tashuvchi tokenni olib tashlash uchun `WithoutToken` usulidan foydalaning: ```go response, err := facades.Http(). @@ -235,10 +226,10 @@ response, err := facades.Http(). Get("https://api.example.com/api/resource") ``` -### Context +### Kontekst -You can use `WithContext` to make your HTTP requests context-aware. -This allows you to control the lifecycle of a request, for instance, by setting timeouts or enabling cancellation. +HTTP so'rovlaringizni kontekstga moslashtirish uchun "WithContext" dan foydalanishingiz mumkin. +Bu sizga so'rovning hayot aylanishini boshqarish imkonini beradi, masalan, vaqtni belgilash yoki bekor qilishni yoqish orqali. ```go ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) @@ -247,9 +238,9 @@ defer cancel() response, err := facades.Http().WithContext(ctx).Get("https://example.com") ``` -### Bind Response +### Bog'lanish javobi -You can use the `Bind` method to specify the struct that the response should be bound to. +Javob bog'lanishi kerak bo'lgan tuzilmani belgilash uchun siz "Bind" usulidan foydalanishingiz mumkin. ```go type User struct { @@ -277,7 +268,7 @@ func main() { ### Cookie -To send cookies with your HTTP requests, you can use `WithCookie` for a single cookie or `WithCookies` for multiple cookies. +HTTP so'rovlaringiz bilan cookie-fayllarni yuborish uchun bitta cookie-fayl uchun `WithCookie` yoki bir nechta cookie-fayllar uchun `WithCookies` dan foydalanishingiz mumkin. ```go response, err := facades.Http(). @@ -293,7 +284,7 @@ response, err := facades.Http(). Get("https://example.com/dashboard") ``` -To prevent specific cookies from being sent with your request, you can use `WithoutCookie`. +So'rovingiz bilan birga ma'lum cookie-fayllar yuborilishining oldini olish uchun siz "WithoutCookie" dan foydalanishingiz mumkin. ```go response, err := facades.Http(). @@ -301,36 +292,32 @@ response, err := facades.Http(). Get("https://example.com") ``` -## Testing +## Sinov -When testing your application, you often want to avoid making real network requests to external APIs. Whether it's to -speed up tests, avoid rate limits, or simulate failure scenarios, Goravel makes this easy. The `Http` facade provides a -powerful `Fake` method that allows you to instruct the HTTP client to return stubbed (dummy) responses when requests are made. +Ilovangizni sinab ko'rishda ko'pincha tashqi API-larga haqiqiy tarmoq so'rovlarini yuborishdan qochishingiz kerak. Goravel testlarni tezlashtirish, tezlik chegaralaridan qochish yoki muvaffaqiyatsizlik stsenariylarini simulyatsiya qilish uchun bo'ladimi, buni osonlashtiradi. “Http” fasadi HTTP mijoziga soʻrovlar yuborilganda notoʻgʻri (soxta) javoblarni qaytarish boʻyicha koʻrsatma berish imkonini beruvchi kuchli “Soxta” usulini taqdim etadi. -### Faking Responses +### Soxta javoblar -To start faking requests, pass a map to the `Fake` method. The keys represent the URL patterns or client names -you want to intercept, and the values represent the responses to return. You can use `*` as a wildcard character. +Soxta so'rovlarni boshlash uchun xaritani "Soxta" usuliga o'tkazing. Kalitlar siz ushlamoqchi bo'lgan URL naqshlarini yoki mijoz nomlarini, qiymatlar esa qaytariladigan javoblarni ifodalaydi. Siz `*` belgisini joker belgi sifatida ishlatishingiz mumkin. -The `Http` facade provides a convenient `Response` builder to construct various types of fake responses. +"Http" jabhasi turli xil soxta javoblarni yaratish uchun qulay "Javob" quruvchisini taqdim etadi. ```go facades.Http().Fake(map[string]any{ - // Stub a specific URL - "https://github.com/goravel/framework": facades.Http().Response().Json(200, map[string]string{"foo": "bar"}), +// Muayyan URL manzilini stubga qo'yish +"https://github.com/goravel/framework": facades.Http().Response().Json(200, map[string]string{"foo": "bar"}), - // Stub a wildcard pattern - "https://google.com/*": facades.Http().Response().String(200, "Hello World"), +// Joker belgili naqshni stubga qo'yish +"https://google.com/*": facades.Http().Response().String(200, "Salom Dunyo"), - // Stub a specific Client (defined in config/http.go) - "github": facades.Http().Response().OK(), +// Muayyan mijozni stubga qo'yish (config/http.go da belgilangan) +"github": facades.Http().Response().OK(), }) ``` -**Fallback URLs** +**Zaxira URL manzillari** -Any request that does not match a pattern defined in `Fake` will be executed normally over the network. To prevent this, -you can define a fallback pattern using the single `*` wildcard, which will match all unmatched URLs. +"Soxta" da belgilangan naqshga mos kelmaydigan har qanday so'rov odatda tarmoq orqali bajariladi. Buning oldini olish uchun, siz barcha mos kelmaydigan URL manzillariga mos keladigan bitta `*` joker belgisidan foydalanib, zaxira nusxasini belgilashingiz mumkin. ```go facades.Http().Fake(map[string]any{ @@ -339,10 +326,9 @@ facades.Http().Fake(map[string]any{ }) ``` -**Implicit Conversions** +**Yashirin konversiyalar** -For convenience, you do not always need to use the `Response` builder. You can pass simple `int`, `string`, or `map` -values, and Goravel will automatically convert them into responses. +Qulaylik uchun, siz har doim ham "Javob" konstruktoridan foydalanishingiz shart emas. Siz oddiy `int`, `string` yoki `map` qiymatlarini uzatishingiz mumkin va Goravel ularni avtomatik ravishda javoblarga aylantiradi. ```go facades.Http().Fake(map[string]any{ @@ -352,45 +338,44 @@ facades.Http().Fake(map[string]any{ }) ``` -### Fake Response Builder +### Soxta javob quruvchisi -The `facades.Http().Response()` method provides a fluent interface to build custom responses easily. +`facades.Http().Response()` usuli maxsus javoblarni osongina yaratish uchun ravon interfeysni ta'minlaydi. ```go -// Create a response using a file content +// Fayl tarkibidan foydalanib javob yarating facades.Http().Response().File(200, "./tests/fixtures/user.json") -// Create a JSON response +// JSON javobini yarating facades.Http().Response().Json(201, map[string]any{"created": true}) -// Create a response with custom headers -headers := http.Header{} +// Maxsus sarlavhalar bilan javob yarating +sarlavhalar := http.Header{} headers.Add("X-Custom", "Value") -facades.Http().Response().Make(200, "Body Content", headers) +facades.Http().Response().Make(200, "Body Content", sarlavhalar) -// Standard status helpers +// Standart holat yordamchilari facades.Http().Response().OK() -facades.Http().Response().Status(403) +facades.Http().Response().Holat(403) ``` -### Faking Response Sequences +### Soxta javob ketma-ketliklari -Sometimes you may need to specify that a single URL should return a series of different responses in order, -such as when testing retries or rate-limiting logic. You can use the `Sequence` method to build this flow. +Ba'zan bitta URL bir qator turli xil javoblarni ketma-ket qaytarishi kerakligini belgilashingiz kerak bo'lishi mumkin, masalan, qayta urinishlarni sinab ko'rish yoki tezlikni cheklovchi mantiqni sinab ko'rish paytida. Ushbu oqimni yaratish uchun siz "Ketma-ketlik" usulidan foydalanishingiz mumkin. ```go facades.Http().Fake(map[string]any{ - "github": facades.Http().Sequence(). - PushStatus(500). // 1st Request: Server Error - PushString(429, "Rate Limit"). // 2nd Request: Rate Limit - PushStatus(200), // 3rd Request: Success +"github": facades.Http().Sequence(). +PushStatus(500). // Birinchi so'rov: Server xatosi +PushString(429, "Tezlik chegarasi"). // Ikkinchi so'rov: Tezlik chegarasi +PushStatus(200), // Uchinchi so'rov: Muvaffaqiyatli }) ``` -**Empty Sequences** +**Bo'sh ketma-ketliklar** -When all responses in a sequence have been consumed, any further requests will cause the client to return an error. -If you wish to specify a default response instead of failing, use the `WhenEmpty` method: +Ketma-ketlikdagi barcha javoblar tugagach, keyingi so'rovlar mijozning xato qaytarishiga olib keladi. +Agar xato qilish o'rniga standart javobni ko'rsatmoqchi bo'lsangiz, `WhenEmpty` usulidan foydalaning: ```go facades.Http().Fake(map[string]any{ @@ -400,10 +385,10 @@ facades.Http().Fake(map[string]any{ }) ``` -### Inspecting Requests +### Tekshirish so'rovlari -When faking responses, it is crucial to verify that the correct requests were actually sent by your application. -You can use the `AssertSent` method to inspect the request and return a boolean indicating if it matches your expectations. +Soxta javoblar berishda, to'g'ri so'rovlar aslida sizning arizangiz tomonidan yuborilganligini tekshirish juda muhimdir. +Siz so'rovni tekshirish va uning sizning kutganlaringizga mos kelishini ko'rsatuvchi mantiqiy qiymatni qaytarish uchun "AssertSent" usulidan foydalanishingiz mumkin. ```go facades.Http().AssertSent(func(req client.Request) bool { @@ -414,9 +399,9 @@ facades.Http().AssertSent(func(req client.Request) bool { }) ``` -**Other Assertions** +**Boshqa tasdiqlar** -You can also assert that a specific request was _not_ sent, or check the total number of requests sent: +Shuningdek, ma'lum bir so'rov _yuborilmagan_ligini tasdiqlashingiz yoki yuborilgan so'rovlarning umumiy sonini tekshirishingiz mumkin: ```go // Assert a request was NOT sent @@ -431,28 +416,25 @@ facades.Http().AssertNothingSent() facades.Http().AssertSentCount(3) ``` -### Preventing Stray Requests +### Noto'g'ri so'rovlarning oldini olish -To ensure your tests are strictly isolated and do not accidentally hit real external APIs, you can use the -`PreventStrayRequests` method. After calling this, any request that does not match a defined Fake rule will cause the -test to panic with an exception. +Sinovlaringiz qat'iy izolyatsiya qilinganligiga va tasodifan haqiqiy tashqi API-larga tegmasligiga ishonch hosil qilish uchun siz "PreventStrayRequests" usulidan foydalanishingiz mumkin. Buni chaqirgandan so'ng, belgilangan Fake qoidasiga mos kelmaydigan har qanday so'rov testni istisno bilan vahimaga soladi. ```go facades.Http().Fake(map[string]any{ - "github": facades.Http().Response().OK(), +"github": facades.Http().Response().OK(), }).PreventStrayRequests() -// This request is mocked and succeeds -facades.Http().Client("github").Get("/") +// Bu so'rov masxara qilindi va muvaffaqiyatli bajarildi +facades.Http().Client("github").Get("/") -// This request is NOT mocked and will panic -facades.Http().Get("https://google.com") +// Bu so'rov masxara qilinmadi va vahimaga tushadi +facades.Http().Get("https://google.com") ``` -**Allowing Specific Strays** +**Maxsus adashganlarga ruxsat berish** -If you need to block most requests but allow specific internal services (like a local test server), -you can use `AllowStrayRequests`: +Agar siz ko'pgina so'rovlarni bloklashingiz kerak bo'lsa, lekin ma'lum ichki xizmatlarga (masalan, mahalliy sinov serveriga) ruxsat berishingiz kerak bo'lsa, siz "AllowStrayRequests" dan foydalanishingiz mumkin: ```go facades.Http().PreventStrayRequests().AllowStrayRequests([]string{ @@ -460,26 +442,22 @@ facades.Http().PreventStrayRequests().AllowStrayRequests([]string{ }) ``` -### Resetting State +### Holatni tiklash -The `Http` facade is a singleton, meaning mocked responses persist across the entire runtime of your test suite unless -cleared. To avoid "leaking" mocks from one test to another, you should strictly use the `Reset` method in -your test cleanup or setup. +"Http" fasadi singleton bo'lib, ya'ni masxara qilingan javoblar tozalanmaguncha sinov to'plamingizning butun ish vaqtida saqlanib qoladi. Bir testdan ikkinchisiga "oqish" holatlarining oldini olish uchun testni tozalash yoki sozlashda qat'iy ravishda "Qayta tiklash" usulidan foydalanishingiz kerak. ```go func TestExternalApi(t *testing.T) { - defer facades.Http().Reset() - - facades.Http().Fake(nil) - - // ... assertions +fasadlarni kechiktirish.Http().Qayta tiklash() + +fasadlar.Http().Soxta(nil) + +// ... tasdiqlar } ``` -:::warning Global State & Parallel Testing -The `Fake` and `Reset` methods mutate the global state of the HTTP client factory. Because of this, **you should avoid -running tests that mock the HTTP client in parallel** (using `t.Parallel()`). Doing so may result in race conditions -where one test resets the mocks while another is still running. +:::warning Global holat va parallel sinovlar +"Soxta" va "Qayta tiklash" usullari HTTP mijoz fabrikasining global holatini o'zgartiradi. Shu sababli, **siz HTTP mijozini parallel ravishda** (`t.Parallel()` yordamida) soxtalashtiradigan testlarni ishga tushirishdan qochishingiz kerak. Buni qilish poyga sharoitlariga olib kelishi mumkin, bunda bitta sinov modellarni qayta o'rnatadi, boshqasi esa hali ham ishlayapti. ::: From 6dac2f6297d0da965cd0af473014f904b101bac1 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Fri, 3 Apr 2026 15:00:37 +0800 Subject: [PATCH 097/163] New translations localization.md (Uzbek) [skip ci] Update translations (Uzbek) localization.md --- uz_UZ/digging-deeper/localization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uz_UZ/digging-deeper/localization.md b/uz_UZ/digging-deeper/localization.md index 53b8a335e..8dbb3c35c 100644 --- a/uz_UZ/digging-deeper/localization.md +++ b/uz_UZ/digging-deeper/localization.md @@ -2,7 +2,7 @@ [[toc]] -## Introduction +## Kirish Goravel's localization features provide a convenient way to retrieve strings in various languages, making it easy to support multiple languages in your application. Language strings are stored in files in the `lang` directory, and Goravel supports two ways to organize language files: From 2f0556e645c26bfdabc428d87d29cb862fe9f4c9 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Fri, 3 Apr 2026 15:00:38 +0800 Subject: [PATCH 098/163] New translations en.ts (Uzbek) [skip ci] Update translations (Uzbek) en.ts --- .vitepress/config/uz_UZ.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.vitepress/config/uz_UZ.ts b/.vitepress/config/uz_UZ.ts index 0cd2e3f99..5180a6ceb 100644 --- a/.vitepress/config/uz_UZ.ts +++ b/.vitepress/config/uz_UZ.ts @@ -88,7 +88,7 @@ function nav(): DefaultTheme.NavItem[] { text: "Versiyalar", items: [{ text: "v1.17 (Eng so'nggi)", - link: "" + link: 'https://www.goravel.dev/' }, { text: 'v1.16', link: 'https://v116.goravel.dev/' @@ -160,7 +160,7 @@ function sidebarFoundation(): DefaultTheme.SidebarItem[] { } function sidebarBasic(): DefaultTheme.SidebarItem[] { return [{ - text: 'Routing', + text: "Marshrutlash", link: 'routing' }, { text: 'Middleware', From bcb9d3f9b54f8c2646b0f247cc71055c61508810 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Fri, 3 Apr 2026 22:50:07 +0800 Subject: [PATCH 099/163] New translations localization.md (Uzbek) [skip ci] Update translations (Uzbek) localization.md --- uz_UZ/digging-deeper/localization.md | 54 ++++++++++++++-------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/uz_UZ/digging-deeper/localization.md b/uz_UZ/digging-deeper/localization.md index 8dbb3c35c..46fd8a318 100644 --- a/uz_UZ/digging-deeper/localization.md +++ b/uz_UZ/digging-deeper/localization.md @@ -1,12 +1,12 @@ -# Localization +# Mahalliylashtirish [[toc]] ## Kirish -Goravel's localization features provide a convenient way to retrieve strings in various languages, making it easy to support multiple languages in your application. Language strings are stored in files in the `lang` directory, and Goravel supports two ways to organize language files: +Goravelning lokalizatsiya xususiyatlari turli tillardagi satrlarni olishning qulay usulini taqdim etadi, bu esa ilovangizda bir nechta tillarni qo'llab-quvvatlashni osonlashtiradi. Til satrlari `lang` katalogidagi fayllarda saqlanadi va Goravel til fayllarini tartibga solishning ikkita usulini qo'llab-quvvatlaydi: -Each language has its own file: +Har bir tilning o'z fayli bor: ``` /lang @@ -14,7 +14,7 @@ Each language has its own file: cn.json ``` -Or, when there are too many translations, they can be categorized: +Yoki juda ko'p tarjimalar bo'lsa, ularni quyidagicha tasniflash mumkin: ``` /lang @@ -24,11 +24,11 @@ Or, when there are too many translations, they can be categorized: user.json ``` -## Configuring the Locale +## Mahalliy sozlamalarni sozlash -The default language of the application is stored in the `locale` configuration option in the `config/app.go` configuration file. You can modify this value as needed to suit your application's requirements. +Ilovaning standart tili `config/app.go` konfiguratsiya faylidagi `lokal` konfiguratsiya parametrida saqlanadi. Ushbu qiymatni ilovangiz talablariga mos ravishda o'zgartirishingiz mumkin. -You can also use the `SetLocale` method provided by the App Facade to modify the default language for a single `HTTP` request at runtime: +Shuningdek, ish vaqtida bitta "HTTP" so'rovi uchun standart tilni o'zgartirish uchun App Facade tomonidan taqdim etilgan "SetLocale" usulidan foydalanishingiz mumkin: ```go facades.Route().Get("/", func(ctx http.Context) http.Response { @@ -38,24 +38,24 @@ facades.Route().Get("/", func(ctx http.Context) http.Response { }) ``` -You can configure a "fallback locale" that will be used when the current language does not contain the given translation string. Like the default language, the fallback language is also configured in the `config/app.go` configuration file. +Joriy tilda berilgan tarjima satri mavjud bo'lmaganda ishlatiladigan "zaxira lokalizatsiyasi" ni sozlashingiz mumkin. Standart til singari, zaxira tili ham `config/app.go` konfiguratsiya faylida sozlangan. ``` "fallback_locale": "en", ``` -### Determining the Current Locale +### Joriy joylashuvni aniqlash -You can use the `CurrentLocale` and `IsLocale` methods to determine the current `locale` or check if the `locale` is a given value. +Joriy "mahalliy" ni aniqlash yoki "mahalliy" berilgan qiymat ekanligini tekshirish uchun "CurrentLocale" va "IsLocale" usullaridan foydalanishingiz mumkin. ``` locale := facades.App().CurrentLocale(ctx) if facades.App().IsLocale(ctx, "en") {} ``` -### Defining Translation Strings +### Tarjima satrlarini aniqlash -In language files, you can define single-level or multi-level structures: +Til fayllarida siz bir darajali yoki ko'p darajali tuzilmalarni belgilashingiz mumkin: ```json // lang/en.json @@ -67,11 +67,11 @@ In language files, you can define single-level or multi-level structures: } ``` -### Retrieving Translation Strings +### Tarjima satrlarini olish -You can use the `facades.Lang(ctx).Get()` method to retrieve translation strings from language files. If the language file contains multiple levels, you can use `.` to connect them, and if the language file is in multiple levels of folders, you can use `/` to connect them. +Til fayllaridan tarjima satrlarini olish uchun `facades.Lang(ctx).Get()` usulidan foydalanishingiz mumkin. Agar til fayli bir nechta darajalarni o'z ichiga olsa, ularni ulash uchun `.` dan foydalanishingiz mumkin, agar til fayli bir nechta papkalar darajasida bo'lsa, ularni ulash uchun `/` dan foydalanishingiz mumkin. -For example: +Masalan: ``` // lang/en.json @@ -97,9 +97,9 @@ facades.Lang(ctx).Get("role/user.name") facades.Lang(ctx).Get("role/user.required.user_id") ``` -#### Replacing Parameters in Translation Strings +#### Tarjima satrlarida parametrlarni almashtirish -You can define placeholders in translation strings. All placeholders have the prefix `:`. For example, you can use a placeholder to define a welcome message: +Siz tarjima satrlarida joy egalarini belgilashingiz mumkin. Barcha o'rin egalari `:` prefiksiga ega. Masalan, xush kelibsiz xabarini aniqlash uchun joy egasidan foydalanishingiz mumkin: ```json { @@ -107,7 +107,7 @@ You can define placeholders in translation strings. All placeholders have the pr } ``` -To replace placeholders when retrieving a translation string, you can pass a translation option with the replacement map as the second parameter to the `facades.Lang(ctx).Get()` method: +Tarjima satrini olishda to'ldiruvchilarni almashtirish uchun, `facades.Lang(ctx).Get()` usuliga ikkinchi parametr sifatida almashtirish xaritasi bilan tarjima opsiyasini o'tkazishingiz mumkin: ```go facades.Lang(ctx).Get("welcome", translation.Option{ @@ -117,9 +117,9 @@ facades.Lang(ctx).Get("welcome", translation.Option{ }) ``` -#### Pluralization +#### Ko'pliklashtirish -Pluralization is a complex problem because different languages have various pluralization rules. However, Goravel can help you translate strings based on the pluralization rules you define. By using the `|` character, you can differentiate between the singular and plural forms of a string: +Ko'pliklashtirish murakkab muammodir, chunki turli tillarda turli xil ko'pliklashtirish qoidalari mavjud. Biroq, Goravel siz belgilagan pluralizatsiya qoidalari asosida satrlarni tarjima qilishga yordam berishi mumkin. `|` belgisidan foydalanib, satrning birlik va ko'plik shakllarini farqlashingiz mumkin: ```json { @@ -127,7 +127,7 @@ Pluralization is a complex problem because different languages have various plur } ``` -You can even create more complex pluralization rules by specifying translation strings for multiple value ranges: +Hatto bir nechta qiymat diapazonlari uchun tarjima satrlarini belgilash orqali yanada murakkab plyuralizatsiya qoidalarini yaratishingiz mumkin: ```json { @@ -135,13 +135,13 @@ You can even create more complex pluralization rules by specifying translation s } ``` -After defining a translation string with pluralization options, you can use the `facades.Lang(ctx).Choice()` method to retrieve the line for a given `count`. In this example, because the count is greater than 1, the plural form of the translation string is returned: +Ko'paytirish parametrlari bilan tarjima satrini aniqlagandan so'ng, berilgan `count` uchun qatorni olish uchun `facades.Lang(ctx).Choice()` usulidan foydalanishingiz mumkin. Bu misolda, son 1 dan katta bo'lgani uchun, tarjima satrining ko'plik shakli qaytariladi: ```go facades.Lang(ctx).Choice("messages.apples", 10) ``` -You can also define placeholder attributes in pluralization strings. By passing an array as the third parameter to the `facades.Lang(ctx).Choice()` method, you can replace these placeholders: +Shuningdek, pluralizatsiya satrlarida joy egallovchi atributlarni ham belgilashingiz mumkin. Massivni `facades.Lang(ctx).Choice()` usuliga uchinchi parametr sifatida o'tkazish orqali siz ushbu o'rinbosarlarni almashtirishingiz mumkin: ``` "minutes_ago": "{1} :value minute ago|[2,*] :value minutes ago", @@ -153,11 +153,11 @@ facades.Lang(ctx).Choice("time.minutes_ago", 5, translation.Option{ }) ``` -## Embed Loading +## Joylashtirish yuklanmoqda -When using embed loading, the language files will be compiled into the binary file and no longer need to be deployed. The independent language files and embed loading can be used at the same time, just configure `lang_path` and `lang_fs` in the `config/app.go` file. When using, the independent language file mode will be used first, and when the independent language file does not exist, the embed loading will be used. +Embed yuklashdan foydalanilganda, til fayllari ikkilik faylga kompilyatsiya qilinadi va endi ularni joylashtirish shart emas. Mustaqil til fayllari va joylashtirish yuklamasi bir vaqtning o'zida ishlatilishi mumkin, shunchaki `config/app.go` faylida `lang_path` va `lang_fs` ni sozlang. Foydalanishda avval mustaqil til fayli rejimi ishlatiladi va mustaqil til fayli mavjud bo'lmaganda, joylashtirish yuklamasi ishlatiladi. -In the same directory as the language files, create a `fs.go` file: +Til fayllari bilan bir xil katalogda `fs.go` faylini yarating: ``` /lang @@ -176,7 +176,7 @@ import "embed" var FS embed.FS ``` -Then configure in the `config/app.go` file: +Keyin `config/app.go` faylida sozlang: ```go // config/app.go From 732a6af3f29262d9297fa49f8b5890d994a2705c Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 4 Apr 2026 00:05:21 +0800 Subject: [PATCH 100/163] New translations mail.md (Uzbek) [skip ci] Update translations (Uzbek) mail.md --- uz_UZ/digging-deeper/mail.md | 58 ++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/uz_UZ/digging-deeper/mail.md b/uz_UZ/digging-deeper/mail.md index d4b9937dd..4a9a253f9 100644 --- a/uz_UZ/digging-deeper/mail.md +++ b/uz_UZ/digging-deeper/mail.md @@ -1,16 +1,16 @@ -# Mail +# Pochta [[toc]] -## Introduction +## Kirish -Goravel can use `facades.Mail()` to easily send mail locally. +Goravel pochtani mahalliy ravishda osongina yuborish uchun `facades.Mail()` dan foydalanishi mumkin. -## Configuration +## Konfiguratsiya -Before sending an email, you need to configure the `config/mail.go` configuration file. +Elektron pochta xabarini yuborishdan oldin, siz `config/mail.go` konfiguratsiya faylini sozlashingiz kerak. -## Send Mail +## Pochta yuborish ```go import "github.com/goravel/framework/mail" @@ -19,13 +19,13 @@ err := facades.Mail().To([]string{"example@example.com"}). Cc([]string{"example@example.com"}). Bcc([]string{"example@example.com"}). Attach([]string{"file.png"}). - Content(mail.Html("

Hello Goravel

")). + Content(mail.Html("<0>Hello Goravel")). Headers(map[string]string{"X-Mailer": "Goravel"}). Subject("Subject"). Send() ``` -## Send Mail By Queue +## Navbat bo'yicha xat yuborish ```go import "github.com/goravel/framework/mail" @@ -40,7 +40,7 @@ err := facades.Mail().To([]string{"example@example.com"}). Queue() ``` -You can also customize the queue: +Siz shuningdek, navbatni sozlashingiz mumkin: ```go import "github.com/goravel/framework/mail" @@ -49,15 +49,15 @@ err := facades.Mail().To([]string{"example@example.com"}). Cc([]string{"example@example.com"}). Bcc([]string{"example@example.com"}). Attach([]string{"file.png"}). - Content(mail.Html("

Hello Goravel

")). + Content(mail.Html("<0>Hello Goravel")). Subject("Subject"). Headers(map[string]string{"X-Mailer": "Goravel"}). Queue(mail.Queue().Connection("redis").Queue("mail")) ``` -## Setting Sender +## Yuboruvchini sozlash -Framework uses `MAIL_FROM_ ADDRESS` and `MAIL_FROM_ NAME` in the `config/mail.go` configuration file as global senders. You can also customize the sender, but you need to note that the mail address needs to be consistent with the configured STMP: +Framework global jo'natuvchilar sifatida `config/mail.go` konfiguratsiya faylida `MAIL_FROM_ ADDRESS` va `MAIL_FROM_ NAME` dan foydalanadi. Siz shuningdek, jo'natuvchini sozlashingiz mumkin, ammo pochta manzili sozlangan STMP bilan mos kelishi kerakligini yodda tutishingiz kerak: ```go import "github.com/goravel/framework/mail" @@ -67,21 +67,21 @@ err := facades.Mail().To([]string{"example@example.com"}). Cc([]string{"example@example.com"}). Bcc([]string{"example@example.com"}). Attach([]string{"file.png"}). - Content(mail.Html("

Hello Goravel

")). + Content(mail.Html("<0>Hello Goravel")). Headers(map[string]string{"X-Mailer": "Goravel"}). Subject("Subject"). Queue(mail.Queue().Connection("redis").Queue("mail")) ``` -## Using Mailable +## Mailable’dan foydalanish -The parameters of the email can be set in a `Mailable` struct. These structs are stored in the `app/mails` directory. You can quickly create a `Mailable` using the `make:mail` Artisan command: +Elektron pochta parametrlarini "Mailable" tuzilmasida o'rnatish mumkin. Ushbu tuzilmalar `app/mails` katalogida saqlanadi. Siz "make:mail" Artisan buyrug'i yordamida tezda "Mailable" yaratishingiz mumkin: ```bash -go run . artisan make:mail OrderShipped +yugurishga boring. hunarmand yasash: pochta orqali buyurtma yuborildi ``` -The generated `OrderShipped` struct is as follows: +Yaratilgan `OrderShipped` tuzilmasi quyidagicha: ```go import "github.com/goravel/framework/contracts/mail" @@ -104,7 +104,7 @@ func (m *OrderShipped) Attachments() []string { } func (m *OrderShipped) Content() *mail.Content { - return &mail.Content{Html: "

Hello Goravel

"} + return &mail.Content{Html: "<0>Hello Goravel"} } func (m *OrderShipped) Envelope() *mail.Envelope { @@ -125,20 +125,20 @@ func (m *OrderShipped) Queue() *mail.Queue { } ``` -Then you can use the `Mailalbe` in the `Send` and `Queue` methods: +Keyin siz "Send" va "Queue" usullarida "Mailalbe" dan foydalanishingiz mumkin: ```go err := facades.Mail().Send(mails.NewOrderShipped()) err := facades.Mail().Queue(mails.NewOrderShipped()) ``` -## Using Template +## Shablondan foydalanish -The mail module now supports using templates directly with the `html/template` engine. This allows you to render email templates with dynamic data. +Pochta moduli endi shablonlardan to'g'ridan-to'g'ri `html/template` dvigateli yordamida foydalanishni qo'llab-quvvatlaydi. Bu sizga elektron pochta shablonlarini dinamik ma'lumotlar bilan ko'rsatish imkonini beradi. -### Configuration +### Konfiguratsiya -To enable template support, configure the `config/mail.go` file: +Andoza qo'llab-quvvatlashini yoqish uchun `config/mail.go` faylini sozlang: ```go "template": map[string]any{ @@ -152,9 +152,9 @@ To enable template support, configure the `config/mail.go` file: } ``` -### Creating Templates +### Shablonlar yaratish -Create your email templates in the specified views directory. For example: +Belgilangan ko'rinishlar katalogida elektron pochta shablonlaringizni yarating. Masalan: ```html @@ -162,9 +162,9 @@ Create your email templates in the specified views directory. For example:

Thank you for joining {{.AppName}}.

``` -### Sending Emails with Templates +### Shablonlar yordamida elektron pochta xabarlarini yuborish -You can use the `Content` method to specify the template and pass dynamic data: +Shablonni belgilash va dinamik ma'lumotlarni uzatish uchun siz "Content" usulidan foydalanishingiz mumkin: ```go facades.Mail(). @@ -180,9 +180,9 @@ facades.Mail(). Send() ``` -### Custom Template Engines +### Maxsus shablon dvigatellari -You can also register custom template engines in the configuration: +Siz shuningdek, konfiguratsiyada maxsus shablon dvigatellarini ro'yxatdan o'tkazishingiz mumkin: ```go "template": map[string]any{ From 57546126e0c9a3414fcbbb14739ca80b3be78209 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 4 Apr 2026 00:05:22 +0800 Subject: [PATCH 101/163] New translations package-development.md (Uzbek) [skip ci] Update translations (Uzbek) package-development.md --- uz_UZ/digging-deeper/package-development.md | 88 ++++++++++----------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/uz_UZ/digging-deeper/package-development.md b/uz_UZ/digging-deeper/package-development.md index 3771bc728..deee98070 100644 --- a/uz_UZ/digging-deeper/package-development.md +++ b/uz_UZ/digging-deeper/package-development.md @@ -1,40 +1,40 @@ -# Package Development +# Paketlarni ishlab chiqish [[toc]] -## Introduction +## Kirish -Packages are the primary way of adding functionality to Goravel. These packages may contain routes, controllers, and configurations that are specifically designed to enhance a Goravel application. This guide focuses on developing Goravel-specific packages. +Paketlar Goravelga funksiyalarni qo'shishning asosiy usuli hisoblanadi. Ushbu paketlar Goravel dasturini takomillashtirish uchun maxsus ishlab chiqilgan marshrutlar, kontrollerlar va konfiguratsiyalarni o'z ichiga olishi mumkin. Ushbu qo'llanma Goravelga xos paketlarni ishlab chiqishga qaratilgan. -Here is an example for building a third-party package: [goravel/example-package](https://github.com/goravel/example-package) +Uchinchi tomon paketini yaratishga misol: [goravel/example-package](https://github.com/goravel/example-package) -## Creating A Package +## Paket yaratish -You can use easily create a package template using the Artisan command: +Artisan buyrug'i yordamida osongina paket shablonini yaratishingiz mumkin: ```shell ./artisan make:package sms ``` -The created files are saved by default in the root `packages` folder, you can use `--root` option to customize: +Yaratilgan fayllar sukut bo'yicha `packages` asosiy papkasida saqlanadi, siz sozlash uchun `--root` parametridan foydalanishingiz mumkin: ```shell ./artisan make:package --root=pkg sms ``` -## Service Providers +## Xizmat ko'rsatuvchilar -[Service providers](../architecture-concepts/service-providers.md) act as the bridge between your package and Goravel. They are typically located in the root of the package as a `service_provider.go` file. Their main function is to bind items into Goravel's service container and guide Goravel in loading package resources. +[Xizmat ko'rsatuvchi provayderlar](../architecture-concepts/service-providers.md) sizning paketingiz va Goravel o'rtasida ko'prik vazifasini bajaradi. Ular odatda paketning ildiz qismida `service_provider.go` fayli sifatida joylashgan. Ularning asosiy vazifasi Goravel xizmat konteyneriga narsalarni bog'lash va Goravelga paket resurslarini yuklashda yo'l-yo'riq ko'rsatishdir. -## Install The Package +## Paketni o'rnating -When creating a package, if it contains a `setup/setup.go` file, you can define the package installation logic in this file, and then users can use the `package:install` command to install the package: +Paket yaratishda, agar unda `setup/setup.go` fayli bo'lsa, siz ushbu faylda paketni o'rnatish mantig'ini belgilashingiz mumkin va keyin foydalanuvchilar paketni o'rnatish uchun `package:install` buyrug'idan foydalanishlari mumkin: ```shell -./artisan package:install github.com/goravel/example-package +./artisan to'plami: github.com/goravel/example-package ni o'rnating ``` -The following is an explanation of the installation process defined in the `setup/setup.go` file, which helps you write your own package installation logic: +Quyida `setup/setup.go` faylida belgilangan o'rnatish jarayonining tushuntirishi keltirilgan, bu sizga o'zingizning paket o'rnatish mantig'ingizni yozishga yordam beradi: ```go // setup/setup.go @@ -50,11 +50,11 @@ import ( ) func main() { - // Initialize setup to get paths, this should be called at the beginning. + // Yo'llarni olish uchun sozlashni ishga tushiring, bu boshida chaqirilishi kerak. setup := packages.Setup(os.Args) - // The config file will be published to the project's config directory automatically when installing by this way. - // You can also publish this config file manually: ./artisan vendor:publish --package=github.com/goravel/example-package + // Shu tarzda o'rnatishda konfiguratsiya fayli avtomatik ravishda loyihaning konfiguratsiya katalogiga nashr etiladi. + // Ushbu konfiguratsiya faylini qo'lda ham nashr qilishingiz mumkin: ./artisan vendor:publish --package=github.com/goravel/example-package config, err := file.GetPackageContent(setup.Paths().Module().String(), "setup/config/hello.go") if err != nil { panic(err) @@ -64,26 +64,26 @@ func main() { moduleImport := setup.Paths().Module().Import() setup.Install( - // Register the service provider to the providers slice in bootstrap/providers.go + // Xizmat ko'rsatuvchi provayderni bootstrap/providers.go saytidagi provayderlar bo'limida ro'yxatdan o'tkazing modify.RegisterProvider(moduleImport, serviceProvider), - // Add the config file to the config directory + // Konfiguratsiya faylini konfiguratsiya katalogiga qo'shing modify.File(path.Config("hello.go")).Overwrite(config), ).Uninstall( - // Remove the config file from the config directory + // Konfiguratsiya faylini konfiguratsiya katalogidan olib tashlang modify.File(path.Config("hello.go")).Remove(), - // Unregister the service provider from the providers slice in bootstrap/providers.go + // bootstrap/providers.go saytidagi provayderlar bo'limidan xizmat ko'rsatuvchi provayderni ro'yxatdan o'chirish modify.UnregisterProvider(moduleImport, serviceProvider), ).Execute() } ``` -## Resources +## Resurslar -### Configuration +### Konfiguratsiya -Typically, you will need to publish your package's configuration file to the application's `config` directory. This will allow users of your package to easily override your default configuration options. To allow your configuration files to be published, call the `Publishes` method from the `Boot` method of your service provider, the first parameter is the package name, and the second parameter is the mapping between the current package file path and the project path: +Odatda, siz paketingizning konfiguratsiya faylini ilovaning "config" katalogiga nashr qilishingiz kerak bo'ladi. Bu sizning paketingiz foydalanuvchilariga standart konfiguratsiya parametrlarini osongina bekor qilish imkonini beradi. Konfiguratsiya fayllaringizni nashr etishga ruxsat berish uchun xizmat ko'rsatuvchi provayderingizning `Boot` usulidan `Publishes` usulini chaqiring, birinchi parametr paket nomi, ikkinchi parametr esa joriy paket fayl yo'li va loyiha yo'li o'rtasidagi xaritalashdir: ```go func (receiver *ServiceProvider) Boot(app foundation.Application) { @@ -93,9 +93,9 @@ func (receiver *ServiceProvider) Boot(app foundation.Application) { } ``` -### Routes +### Yo'nalishlar -If there are [routes](../the-basics/routing.md) in your package, you can use `app.MakeRoute()` to resolve `facades.Route()`, then add the routes to the project: +Agar paketingizda [routes](../the-basics/routing.md) mavjud bo'lsa, `facades.Route()` ni hal qilish uchun `app.MakeRoute()` dan foydalanishingiz mumkin, keyin esa loyihaga marshrutlarni qo'shishingiz mumkin: ```go func (receiver *ServiceProvider) Boot(app foundation.Application) { @@ -104,9 +104,9 @@ func (receiver *ServiceProvider) Boot(app foundation.Application) { } ``` -### Migrations +### Migratsiyalar -If there are [migrations](../database/migrations.md) in your package, you can publish them by the `Publishes` method: +Agar paketingizda [migrations](../database/migrations.md) mavjud bo'lsa, ularni `Publishes` usuli bilan nashr qilishingiz mumkin: ```go func (receiver *ServiceProvider) Boot(app foundation.Application) { @@ -116,9 +116,9 @@ func (receiver *ServiceProvider) Boot(app foundation.Application) { } ``` -### Models +### Modellar -If there are any new [models](../orm/getting-started.md) defined as part of your package, they can be published using the `Publishes` method: +Agar paketingizning bir qismi sifatida belgilangan yangi [modellar](../orm/getting-started.md) bo'lsa, ularni `Nashr qilish` usuli yordamida nashr etish mumkin: ```go func (receiver *ServiceProvider) Boot(app foundation.Application) { @@ -128,9 +128,9 @@ func (receiver *ServiceProvider) Boot(app foundation.Application) { } ``` -## Commands +## Buyruqlar -You can register `Artisan` command by the `Commands` method, you can run the commands using [Artisan CLI](../digging-deeper/artisan-console.md) after registering them. +Siz `Artisan` buyrug'ini `Commands` usuli bilan ro'yxatdan o'tkazishingiz mumkin, buyruqlarni ro'yxatdan o'tkazgandan so'ng ularni [Artisan CLI](../digging-deeper/artisan-console.md) yordamida ishga tushirishingiz mumkin. ```go func (receiver *ServiceProvider) Boot(app foundation.Application) { @@ -140,9 +140,9 @@ func (receiver *ServiceProvider) Boot(app foundation.Application) { } ``` -## Public Assets +## Davlat aktivlari -Your package may have assets such as JavaScript, CSS, and images. To publish these assets to the application's `public` directory, use the service provider's `Publishes` method: +Paketingizda JavaScript, CSS va rasmlar kabi aktivlar bo'lishi mumkin. Ushbu aktivlarni ilovaning "ommaviy" katalogiga nashr qilish uchun xizmat ko'rsatuvchi provayderning "Public" usulidan foydalaning: ```go func (receiver *ServiceProvider) Boot(app foundation.Application) { @@ -152,9 +152,9 @@ func (receiver *ServiceProvider) Boot(app foundation.Application) { } ``` -## Publishing File Groups +## Fayl guruhlarini nashr qilish -If you want to publish specific groups of package assets and resources separately, you can use tags when calling the `Publishes` method from the package's service provider. This allows you to give users the option to publish certain files, like configuration files, without having to publish all the package's assets. To illustrate, you can define two publish groups for the `sms` package (`sms-config` and `sms-migrations`) using tags in the `Boot` method of the package's service provider. +Agar siz paket aktivlari va resurslarining ma'lum guruhlarini alohida nashr qilmoqchi bo'lsangiz, paket xizmat ko'rsatuvchi provayderidan "Nashr qilish" usulini chaqirishda teglardan foydalanishingiz mumkin. Bu sizga foydalanuvchilarga konfiguratsiya fayllari kabi ma'lum fayllarni paketning barcha aktivlarini nashr qilmasdan nashr qilish imkoniyatini berish imkonini beradi. Misol tariqasida, paket xizmat ko'rsatuvchi provayderining "Boot" usulidagi teglar yordamida "sms" paketi uchun ikkita nashr guruhini ("sms-config" va "sms-migrations") belgilashingiz mumkin. ```go func (receiver *ServiceProvider) Boot(app foundation.Application) { @@ -167,19 +167,19 @@ func (receiver *ServiceProvider) Boot(app foundation.Application) { } ``` -## Publish Resources +## Resurslarni nashr qilish -In the project, You can publish the resources registered in a package using `vendor:publish` Artisan command: +Loyihada siz "vendor:publish" Artisan buyrug'i yordamida paketda ro'yxatdan o'tgan resurslarni nashr qilishingiz mumkin: ```shell ./artisan vendor:publish --package={You package name} ``` -The command can use the following options: +Buyruq quyidagi variantlardan foydalanishi mumkin: -| Option Name | Alias | Action | -| ----------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| --package | -p | Package name, can be a remote package: `github.com/goravel/example-package`, and also can be a local package: `./packages/example-package`, note that when using a local package name, it needs to start with `./`. | -| --tag | -t | Resource Group | -| --force | -f | Overwrite any existing files | -| --existing | -e | Publish and overwrite only the files that have already been published | +| Variant nomi | Taxallus | Harakat | +| ------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| --package | -p | Paket nomi masofaviy paket bo'lishi mumkin: `github.com/goravel/example-package`, shuningdek, mahalliy paket bo'lishi mumkin: `./packages/example-package`, mahalliy paket nomidan foydalanganda u `./` bilan boshlanishi kerakligini unutmang. | +| --tag | -t | Resurslar guruhi | +| --force | -f | Mavjud fayllarni qayta yozing | +| --existing | -e | Faqat allaqachon nashr etilgan fayllarni nashr eting va qayta yozing | From a7e3b736b8e9d49f634e4b74dfb6b778f6c55d70 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 4 Apr 2026 02:22:29 +0800 Subject: [PATCH 102/163] New translations pluralization.md (Uzbek) [skip ci] Update translations (Uzbek) pluralization.md --- uz_UZ/digging-deeper/pluralization.md | 69 +++++++++++++-------------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/uz_UZ/digging-deeper/pluralization.md b/uz_UZ/digging-deeper/pluralization.md index 59c437fcd..a36c6df09 100644 --- a/uz_UZ/digging-deeper/pluralization.md +++ b/uz_UZ/digging-deeper/pluralization.md @@ -1,40 +1,38 @@ -# Pluralization +# Ko'pliklashtirish [[toc]] -## Introduction +## Kirish -Strings are important for any web application. Goravel provides simple utilities to convert words between singular -and plural forms. It supports **English** by default, but you can add other languages or custom rules easily. +Satrlar har qanday veb-ilova uchun muhimdir. Goravel so'zlarni birlik va ko'plik shakllariga aylantirish uchun oddiy yordamchi dasturlarni taqdim etadi. Sukut bo'yicha **inglizcha** ni qo'llab-quvvatlaydi, lekin siz boshqa tillarni yoki maxsus qoidalarni osongina qo'shishingiz mumkin. -## Basic Usage +## Asosiy foydalanish -You can use the `Plural` and `Singular` methods from the `pluralizer` package. These handle most English words automatically. +Siz `pluralizer` paketidagi `Ko'plik` va `Yakkalik` usullaridan foydalanishingiz mumkin. Bular ko'pgina inglizcha so'zlarni avtomatik ravishda qayta ishlaydi. ```go import "github.com/goravel/framework/support/pluralizer" -// Pluralize words +// So'zlarni ko'p sonli qilish pluralizer.Plural("goose") // "geese" pluralizer.Plural("car") // "cars" -// Singularize words +// So'zlarni birlashtirish pluralizer.Singular("geese") // "goose" pluralizer.Singular("cars") // "car" ``` -## Custom Rules +## Maxsus qoidalar -Sometimes the default rules are not enough for specific words. Goravel lets you add your own rules to handle these cases. +Ba'zan standart qoidalar ma'lum so'zlar uchun yetarli emas. Goravel lets you add your own rules to handle these cases. :::warning -Adding rules changes how pluralization works globally. You should do this when your application starts, -like in the `Boot` method of a Service Provider. +Qoidalarni qo'shish plyuralizatsiyaning global miqyosda qanday ishlashini o'zgartiradi. Buni ilova ishga tushganda qilishingiz kerak, masalan, xizmat ko'rsatuvchi provayderning "Yuklash" usulida. ::: -### Irregular Words +### Ingliz tilidagi noto'g'ri fellar -If a word has a unique plural form, you can register it as an "irregular" word. This handles changes in both directions. +Agar so'z noyob ko'plik shakliga ega bo'lsa, uni "tartibsiz" so'z sifatida ro'yxatdan o'tkazishingiz mumkin. Bu ikkala yo'nalishdagi o'zgarishlarni ham boshqaradi. ```go import ( @@ -46,42 +44,41 @@ import ( pluralizer.RegisterIrregular("english", rules.NewSubstitution("mouse", "mice")) ``` -### Uninflected Words +### O'zgartirilmagan so'zlar -Some words like "fish" or "media" do not change form or are always plural. You can mark these as "uninflected" -so the pluralizer skips them. +"Baliq" yoki "media" kabi ba'zi so'zlar shaklini o'zgartirmaydi yoki har doim ko'plikda bo'ladi. Siz ularni "o'zgartirilmagan" deb belgilashingiz mumkin, shuning uchun pluralizer ularni o'tkazib yuboradi. ```go -// "sheep" stays "sheep" in singular and plural +// "sheep" birlik va ko'plikda "sheep" bo'lib qoladi pluralizer.RegisterUninflected("english", "sheep") -// "media" is always treated as plural +// "media" har doim ko'plik sifatida qabul qilinadi pluralizer.RegisterPluralUninflected("english", "media") -// "data" is always treated as singular +// "data" har doim birlik sifatida qabul qilinadi pluralizer.RegisterSingularUninflected("english", "data") ``` -## Language Support +## Til Yordami -Goravel uses "english" by default, but you can switch languages or add new ones if you need to. +Goravel sukut bo'yicha "inglizcha" dan foydalanadi, lekin agar kerak bo'lsa, tillarni almashtirishingiz yoki yangilarini qo'shishingiz mumkin. -### Switching Languages +### Tillarni almashtirish -If you have other languages registered, you can switch the active one using `UseLanguage`. +Agar sizda boshqa tillar ro'yxatdan o'tgan bo'lsa, faol tilni "UseLanguage" yordamida almashtirishingiz mumkin. ```go if err := pluralizer.UseLanguage("spanish"); err != nil { panic(err) } -// Get the current language name +// Joriy til nomini oling name := pluralizer.GetLanguage().Name() ``` -### Adding New Languages +### Yangi tillar qo'shish -To add a language, you need to implement the `Language` interface. This defines how words change in that language. +Til qo'shish uchun siz "Til" interfeysini amalga oshirishingiz kerak. Bu so'zlarning o'sha tilda qanday o'zgarishini belgilaydi. ```go import "github.com/goravel/framework/contracts/support/pluralizer" @@ -93,28 +90,28 @@ type Language interface { } ``` -After implementing your language struct, register it and set it as active. +Til tuzilmangizni amalga oshirgandan so'ng, uni ro'yxatdan o'tkazing va faol deb o'rnating. ```go import "github.com/goravel/framework/support/pluralizer" func init() { - // Register the new language + // Yangi tilni ro'yxatdan o'tkazing if err := pluralizer.RegisterLanguage(&MyCustomLanguage{}); err != nil { panic(err) } - // Set it as active + // Uni faol sifatida o'rnating _ = pluralizer.UseLanguage("my_custom_language") } ``` -## Supported Languages +## Qo'llab-quvvatlanadigan tillar -Currently, the pluralizer supports the following languages out of the box: +Hozirda pluralizer quyidagi tillarni darhol qo'llab-quvvatlaydi: -| Language | Code | Source | -| :------- | :-------- | :----------------------------------------------------------------------------------------- | -| English | `english` | [View Source](https://github.com/goravel/framework/tree/master/support/pluralizer/english) | +| Til | Kod | Manba | +| :-------- | :---------- | :--------------------------------------------------------------------------------------------- | +| Inglizcha | `inglizcha` | [Manbani ko'rish](https://github.com/goravel/framework/tree/master/support/pluralizer/english) | -_More languages will be added in future releases. You are welcome to contribute new languages via Pull Request._ \ No newline at end of file +_Kelajakdagi nashrlarda ko'proq tillar qo'shiladi. Pull Request orqali yangi tillarga hissa qo'shishingiz mumkin._ \ No newline at end of file From fc4a06a218fa9e5b1aa82fe5f6d0f99f347488df Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Sat, 4 Apr 2026 03:57:50 +0800 Subject: [PATCH 103/163] New translations processes.md (Uzbek) [skip ci] Update translations (Uzbek) processes.md --- uz_UZ/digging-deeper/processes.md | 222 ++++++++++++++---------------- 1 file changed, 106 insertions(+), 116 deletions(-) diff --git a/uz_UZ/digging-deeper/processes.md b/uz_UZ/digging-deeper/processes.md index a81d5ac28..3f5613a4c 100644 --- a/uz_UZ/digging-deeper/processes.md +++ b/uz_UZ/digging-deeper/processes.md @@ -1,18 +1,18 @@ -# Processes +# Jarayonlar [[toc]] -## Introduction +## Kirish -Goravel provides an expressive and elegant API around Go's standard `os/exec` package, allowing you to invoke external commands from your application seamlessly. By default, Go's process handling can be verbose; Goravel's `Process` facade simplifies this common task, offering a fluent interface for executing commands, handling output, and managing asynchronous processes. +Goravel Go'ning standart `os/exec` paketi atrofida ifodali va oqlangan API taqdim etadi, bu sizga ilovangizdan tashqi buyruqlarni muammosiz chaqirish imkonini beradi. Odatiy bo'lib, Go'ning jarayonlarni boshqarishi batafsil bo'lishi mumkin; Goravel'ning "Jarayon" jabhasi bu umumiy vazifani soddalashtiradi, buyruqlarni bajarish, chiqishlarni boshqarish va asinxron jarayonlarni boshqarish uchun ravon interfeysni taklif qiladi. -## Invoking Processes +## Jarayonlarni chaqirish -### Running Processes +### Ishlayotgan jarayonlar -To run a process, you can use the `Run` or `Start` methods. The `Run` method will execute the command and wait for it to finish, while the `Start` method triggers the process asynchronously and returns control immediately. +Jarayonni ishga tushirish uchun siz "Run" yoki "Start" usullaridan foydalanishingiz mumkin. `Run` metodi buyruqni bajaradi va uning tugashini kutadi, `Start` metodi esa jarayonni asinxron ravishda ishga tushiradi va boshqaruvni darhol qaytaradi. -Here is how you execute a blocking command: +Bloklash buyrug'ini quyidagicha bajarishingiz mumkin: ```go import ( @@ -31,7 +31,7 @@ func main() { } ``` -If you want to run a string command directly (without splitting it into arguments), you can pass the command to `Run` as a single string, `/bin/sh -c` (Linux/macOS) or `cmd /C` (Windows) will be used under the hood. Notice, the mechanism can only be triggered when the string command contains spaces or `&`, `|`, `-`. +Agar siz satr buyrug'ini to'g'ridan-to'g'ri (argumentlarga ajratmasdan) ishga tushirmoqchi bo'lsangiz, uni `Run` ga bitta satr sifatida uzatishingiz mumkin, buning uchun `/bin/sh -c` (Linux/macOS) yoki `cmd/C` (Windows) ishlatiladi. E'tibor bering, mexanizm faqat satr buyrug'i bo'shliqlar yoki `&`, `|`, `-` belgilarini o'z ichiga olganda ishga tushirilishi mumkin. ```go result := facades.Process().Run("echo Hello, World!") @@ -39,26 +39,26 @@ result := facades.Process().Run("echo Hello, World!") // cmd /c "echo Hello, World!" on Windows ``` -The `Run` method returns a `Result` interface. The `Result` interface gives you convenient access to the output and status of the command: +`Run` usuli `Result` interfeysini qaytaradi. "Result" interfeysi sizga buyruqning chiqishi va holatiga qulay kirish imkonini beradi: ```go result := facades.Process().Run("ls", "-la") -result.Command() // string: The original command -result.Error() // error: The error returned by the command execution -result.ErrorOutput() // string: Output from Stderr -result.ExitCode() // int: The exit code (e.g., 0, 1) -result.Failed() // bool: True if the exit code was not 0 -result.Output() // string: Output from Stdout +result.Command() // string: Asl buyruq +result.Error() // error: Buyruq bajarilishi natijasida qaytarilgan xato +result.ErrorOutput() // string:Stderr dan chiqish +result.ExitCode() // int: Chiqish kodi (masalan, 0, 1) +result.Failed() // bool: Agar chiqish kodi 0 bo'lmasa, rost +result.Output() // string: Stdout dan chiqish ``` -### Process Options +### Jarayon parametrlari -You often need to customize how a command runs, such as where it runs or what environment variables it sees. The `Process` facade provides a fluent API for this. +Ko'pincha buyruq qanday ishlashini, masalan, qayerda ishlashini yoki qanday muhit o'zgaruvchilarini ko'rishini sozlashingiz kerak bo'ladi. "Process" jabhasi buning uchun ravon API taqdim etadi. #### Path -You can use the `Path` method to specify the working directory for the command. If you don't set this, the process will execute in the current working directory of your application. +Buyruq uchun ishchi katalogni ko'rsatish uchun `Path` usulidan foydalanishingiz mumkin. Agar buni o'rnatmasangiz, jarayon ilovangizning joriy ishchi katalogida bajariladi. ```go result := facades.Process().Path("/var/www/html").Run("ls", "-la") @@ -66,7 +66,7 @@ result := facades.Process().Path("/var/www/html").Run("ls", "-la") #### Timeout -To prevent a process from hanging indefinitely, you can enforce a timeout. If the process runs longer than the specified duration, it will be killed. +Jarayonning cheksiz vaqt davomida to'xtab qolishining oldini olish uchun siz tanaffusni amalga oshirishingiz mumkin. Agar jarayon belgilangan vaqtdan uzoqroq davom etsa, u o'chiriladi. ```go import "time" @@ -74,34 +74,34 @@ import "time" result := facades.Process().Timeout(10 * time.Minute).Run("sleep", "20") ``` -#### Environment Variables +#### Atrof-muhit o'zgaruvchilari -You can pass custom environment variables to the process using the `Env` method. The process will also inherit the system's environment variables. +Siz maxsus muhit o'zgaruvchilarini jarayonga `Env` usuli yordamida o'tkazishingiz mumkin. Jarayon shuningdek, tizimning muhit o'zgaruvchilarini meros qilib oladi. ```go -// Passes FOO=BAR along with existing system envs +// FOO=BAR ni mavjud tizim envslari bilan birga o'tkazadi. result := facades.Process().Env(map[string]string{ "FOO": "BAR", "API_KEY": "secret", }).Run("printenv") ``` -#### Input (Stdin) +#### Kirish (Stdin) -If your command expects input from standard input (stdin), you can provide it using the `Input` method. This accepts an `io.Reader`. +Agar sizning buyrug'ingiz standart inputdan (stdin) kirishni kutsa, uni "Input" usuli yordamida taqdim etishingiz mumkin. Bu "io.Reader" ni qabul qiladi. ```go import "strings" -// Pipes "Hello Goravel" into the cat command +// Cat buyrug'iga "Salom Goravel" deb javob beradi result := facades.Process(). Input(strings.NewReader("Hello Goravel")). Run("cat") ``` -### Process Output +### Jarayon chiqishi -You can access the process output after execution using the `Output` (standard output) and `ErrorOutput` (standard error) methods on the result object. +Jarayon natijasiga natija obyektidagi `Output` (standart chiqish) va `ErrorOutput` (standart xato) usullari yordamida bajarilgandan so'ng kirishingiz mumkin. ```go result := facades.Process().Run("ls", "-la") @@ -110,7 +110,7 @@ fmt.Println(result.Output()) fmt.Println(result.ErrorOutput()) ``` -If you need to process the output in real-time (streaming), you may register a callback using the `OnOutput` method. The callback receives two arguments: the output type (stdout or stderr) and the byte slice containing the output data. +Agar siz chiqishni real vaqt rejimida (oqimli) qayta ishlashingiz kerak bo'lsa, "OnOutput" usuli yordamida qayta qo'ng'iroqni ro'yxatdan o'tkazishingiz mumkin. Qayta qo'ng'iroq ikkita argumentni oladi: chiqish turi (stdout yoki stderr) va chiqish ma'lumotlarini o'z ichiga olgan bayt bo'lagi. ```go import ( @@ -119,12 +119,12 @@ import ( ) result := facades.Process().OnOutput(func(typ process.OutputType, b []byte) { - // Handle real-time streaming here + // Bu yerda real vaqt rejimida translyatsiyani boshqaring fmt.Print(string(b)) }).Run("ls", "-la") ``` -If you only need to verify that the output contains a specific string after execution, you can use the `SeeInOutput` or `SeeInErrorOutput` helper methods. +Agar siz faqat bajarilgandan keyin chiqishda ma'lum bir satr borligini tekshirishingiz kerak bo'lsa, siz `SeeInOutput` yoki `SeeInErrorOutput` yordamchi usullaridan foydalanishingiz mumkin. ```go result := facades.Process().Run("ls", "-la") @@ -134,28 +134,27 @@ if result.SeeInOutput("go.mod") { } ``` -#### Disabling Process Output +#### Jarayon chiqishini o'chirib qo'yish -If your process writes a large amount of data, you may want to control how it is stored. +Agar jarayoningiz katta hajmdagi ma'lumotlarni yozsa, uni qanday saqlashni boshqarishingiz mumkin. -Using `Quietly` will prevent the output from bubbling up to the console or logs during execution, but the data will still be collected and available via `result.Output()`. +`Quietly` dan foydalanish chiqish ma'lumotlarining konsolga yoki bajarilish vaqtida jurnallarga pufakchalar bilan chiqishining oldini oladi, ammo ma'lumotlar hali ham to'planadi va `result.Output()` orqali mavjud bo'ladi. -If you do not need to access the final output at all and want to save memory, you can use `DisableBuffering`. This prevents the output from being stored in the result object, though you can still inspect the stream in real-time using `OnOutput`. +Agar siz yakuniy natijaga umuman kirishingiz shart bo'lmasa va xotirani tejashni istasangiz, "DisableBuffering" dan foydalanishingiz mumkin. Bu natija natija obyektida saqlanishiga to'sqinlik qiladi, garchi siz hali ham oqimni real vaqt rejimida "OnOutput" yordamida tekshirishingiz mumkin. ```go -// Captures output but doesn't print it during execution +// Chiqishni yozib oladi, lekin bajarish paytida chop etmaydi facades.Process().Quietly().Run("...") -// Does not capture output (saves memory), but allows streaming +// Chiqishni yozib olmaydi (xotirani tejaydi), lekin oqimli uzatishga imkon beradi facades.Process().DisableBuffering().OnOutput(func(typ process.OutputType, b []byte) { // ... }).Run("...") ``` -### Pipelines +### Quvurlar -Sometimes you need to pipe the output of one process into the input of another. The `Process` facade makes this easy -using the `Pipe` method, which allows you to chain multiple commands together synchronously. +Ba'zan siz bir jarayonning chiqishini boshqa jarayonning kirishiga o'tkazishingiz kerak bo'ladi. `Process` fasadi buni `Pipe` usuli yordamida osonlashtiradi, bu sizga bir nechta buyruqlarni sinxron ravishda birlashtirish imkonini beradi. ```go import "github.com/goravel/framework/contracts/process" @@ -168,26 +167,24 @@ result := facades.Process().Pipe(func(pipe process.Pipe) { ``` :::warning -Process options such as `Timeout`, `Env`, or `Input` must be configured **after** the `Pipe` method is called. -Any configuration applied before the `Pipe` call will be ignored. +`Timeout`, `Env` yoki `Input` kabi jarayon parametrlari `Pipe` usuli chaqirilgandan **keyin** sozlanishi kerak. +`Pipe` chaqiruvidan oldin qo'llanilgan har qanday konfiguratsiya e'tiborga olinmaydi. ```go -// Correct: Configuration applied after Pipe +// To'g'ri: Quvurdan keyin konfiguratsiya qo'llanildi facades.Process().Pipe(...).Timeout(10 * time.Second).Run() -// Incorrect: Timeout will be ignored +// Noto'g'ri: Vaqt tugashi e'tiborga olinmaydi facades.Process().Timeout(10 * time.Second).Pipe(...).Run() ``` ::: -#### Pipeline Output & Keys +#### Quvur liniyasi chiqishi va kalitlari -You can inspect the output of the pipeline in real-time using the `OnOutput` method. When used with a pipe, -the callback signature changes to include a `key` (string), allowing you to identify which command produced the output. +Siz quvur liniyasining chiqishini real vaqt rejimida "OnOutput" usuli yordamida tekshirishingiz mumkin. Quvur bilan ishlatilganda, qayta chaqiruv imzosi `kalit` (satr) ni o'z ichiga oladi, bu sizga qaysi buyruq natijani berganini aniqlash imkonini beradi. -By default, the `key` is the numeric index of the command. However, you can assign a readable label to each command -using the `As` method, which is highly useful for debugging complex pipelines. +Odatiy bo'lib, `key` buyruqning raqamli indeksidir. Biroq, murakkab quvurlarni nosozliklarni tuzatish uchun juda foydali bo'lgan `As` usuli yordamida har bir buyruqqa o'qiladigan yorliq tayinlashingiz mumkin. ```go facades.Process().Pipe(func(pipe process.Pipe) { @@ -198,45 +195,44 @@ facades.Process().Pipe(func(pipe process.Pipe) { }).Run() ``` -## Asynchronous Processes +## Asinxron jarayonlar -While the `Run` method waits for the process to complete, `Start` can be used to invoke a process asynchronously. -This allows the process to run in the background while your application continues executing other tasks. The `Start` method returns a `Running` interface. +`Run` usuli jarayon tugashini kutayotgan bir paytda, `Start` usuli jarayonni asinxron ravishda ishga tushirish uchun ishlatilishi mumkin. +Bu sizning ilovangiz boshqa vazifalarni bajarishda davom etayotgan paytda jarayonning fonda ishlashiga imkon beradi. `Start` usuli `Running` interfeysini qaytaradi. ```go import "time" running, err := facades.Process().Timeout(10 * time.Second).Start("sleep", "5") -// Continue doing other work... +// Boshqa ishlarni davom ettiring... result := running.Wait() ``` -To check if a process has finished without blocking, you may use the `Done` method. This returns a standard Go channel -that closes when the process exits, making it ideal for use in `select` statements. +Jarayon bloklanmasdan tugaganligini tekshirish uchun siz `Done` usulidan foydalanishingiz mumkin. Bu jarayon tugaganda yopiladigan standart Go kanalini qaytaradi, bu esa uni `select` operatorlarida foydalanish uchun ideal qiladi. ```go running, err := facades.Process().Start("sleep", "5") select { case <-running.Done(): - // Process finished successfully + // Jarayon muvaffaqiyatli yakunlandi case <-time.After(1 * time.Second): - // Custom logic if it takes too long + // Agar juda ko'p vaqt talab etilsa, maxsus mantiq } result := running.Wait() ``` :::warning -Even if you use the `Done` channel to detect completion, you **must** call `Wait()` afterwards. -This ensures the process is properly "reaped" by the operating system and cleans up underlying resources. +Bajarilganlikni aniqlash uchun `Done` kanalidan foydalansangiz ham, keyinroq `Wait()` funksiyasini chaqirishingiz **kerak**. +Bu jarayonning operatsion tizim tomonidan to'g'ri "reaped" va asosiy resurslarni tozalashini ta'minlaydi. ::: -### Process IDs & Signals +### Jarayon identifikatorlari va signallari -You can retrieve the operating system's process ID (PID) for a running process using the `PID` method. +Siz `PID` usuli yordamida ishlayotgan jarayon uchun operatsion tizimning jarayon identifikatorini (PID) olishingiz mumkin. ```go running, err := facades.Process().Start("ls", "-la") @@ -244,13 +240,12 @@ running, err := facades.Process().Start("ls", "-la") println(running.PID()) ``` -#### Sending Signals +#### Signallarni yuborish -Goravel provides methods to interact with the process lifecycle. You can send a specific OS signal using -the `Signal` method, or use the `Stop` helper to attempt a graceful shutdown. +Goravel jarayonning hayot aylanishi bilan o'zaro ta'sir qilish usullarini taqdim etadi. Siz `Signal` usuli yordamida ma'lum bir OS signalini yuborishingiz yoki `Stop` yordamchisidan foydalanib, nafis o'chirishga harakat qilishingiz mumkin. -The `Stop` method is particularly useful: it will first send a termination signal (defaulting to `SIGTERM`). -If the process does not exit within the provided timeout, it will be forcibly killed (`SIGKILL`). +`Stop` usuli ayniqsa foydalidir: u avval tugatish signalini yuboradi (standart holatda `SIGTERM` ga o‘rnatiladi). +Agar jarayon belgilangan vaqt ichida tugamasa, u majburan o'chiriladi (`SIGKILL`). ```go import ( @@ -260,40 +255,38 @@ import ( running, err := facades.Process().Start("sleep", "60") -// Manually send a signal +// Signalni qo'lda yuborish running.Signal(os.Interrupt) -// Attempt to stop gracefully, wait 5 seconds, then force kill +// Nafislik bilan to'xtashga harakat qiling, 5 soniya kuting, keyin majburan o'ldiring running.Stop(5 * time.Second) ``` -### Checking Process State +### Jarayon holatini tekshirish -You can inspect the current state of the process using the `Running` method. This is primarily useful for debugging -or health checks, as it provides a snapshot of whether the process is currently active. +Jarayonning joriy holatini `Running` usuli yordamida tekshirishingiz mumkin. Bu, birinchi navbatda, nosozliklarni tuzatish yoki sog'liqni tekshirish uchun foydalidir, chunki u jarayon hozirda faol yoki yo'qligini ko'rsatadi. ```go -// Snapshot check (useful for logs or metrics) -if running.Running() { - fmt.Println("Process is still active...") +// Snapshot tekshiruvi (jurnallar yoki ko'rsatkichlar uchun foydali) +agar running.Running() { +fmt.Println("Jarayon hali ham faol...") } ``` :::tip -If you need to execute code **when** the process finishes, do not poll `Running()`. Instead, use the `Done()` channel -or the `Wait()` method, which are much more efficient than repeatedly checking the status. +Agar jarayon tugashi bilan kodni **ijro etish** kerak bo'lsa, `Running()` funksiyasini so'ramang. Buning o'rniga, holatni qayta-qayta tekshirishdan ko'ra ancha samaraliroq bo'lgan `Done()` kanali yoki `Wait()` usulidan foydalaning. ::: -## Concurrent Processes +## Bir vaqtning o'zida sodir bo'ladigan jarayonlar -Goravel makes it easy to manage a pool of concurrent processes, allowing you to execute multiple commands simultaneously. -This is particularly useful for batch processing or running independent tasks in parallel. +Goravel bir vaqtning o'zida bir nechta buyruqlarni bajarish imkonini beruvchi bir vaqtning o'zida bir nechta jarayonlarni boshqarishni osonlashtiradi. +Bu, ayniqsa, ommaviy ishlov berish yoki mustaqil vazifalarni parallel ravishda bajarish uchun foydalidir. -### Executing Pools +### Hovuzlarni bajarish -To run a pool of processes, you may use the `Pool` method. This accepts a closure where you define the commands you wish to execute. +Jarayonlar pulini ishga tushirish uchun siz `Pool` usulidan foydalanishingiz mumkin. Bu siz bajarmoqchi bo'lgan buyruqlarni belgilaydigan yopilishni qabul qiladi. -By default, the `Pool` method waits for all processes to complete and returns a map of results keyed by the process name (or index). +Odatiy bo'lib, `Pool` usuli barcha jarayonlarning tugashini kutadi va jarayon nomi (yoki indeksi) bilan belgilangan natijalar xaritasini qaytaradi. ```go results, err := facades.Process().Pool(func(pool process.Pool) { @@ -305,108 +298,105 @@ if err != nil { panic(err) } -// Access results by their assigned key +// Natijalarga tayinlangan kalit orqali kirish println(results["first"].Output()) println(results["second"].Output()) ``` -### Naming Processes +### Nomlash jarayonlari -By default, processes in a pool are keyed by their numeric index (e.g., "0", "1"). However, for clarity and easier access -to results, you should assign a unique name to each process using the `As` method: +Odatiy bo'lib, hovuzdagi jarayonlar ularning raqamli indekslari (masalan, "0", "1") bilan belgilanadi. Biroq, natijalarga aniqlik kiritish va osonroq kirish uchun har bir jarayonga `As` usuli yordamida noyob nom berishingiz kerak: ```go pool.Command("cat", "system.log").As("system") ``` -### Pool Options +### Pool imkoniyatlari -The `Pool` builder provides several methods to control the execution behavior of the entire batch. +`Pool` quruvchisi butun partiyaning bajarilish xatti-harakatlarini boshqarish uchun bir nechta usullarni taqdim etadi. #### Concurrency -You can control the maximum number of processes running simultaneously using the `Concurrency` method. +Siz `Concurrency` usuli yordamida bir vaqtning o'zida ishlaydigan jarayonlarning maksimal sonini boshqarishingiz mumkin. ```go facades.Process().Pool(func(pool process.Pool) { - // Define 10 commands... + // 10 ta buyruqni aniqlang... }).Concurrency(2).Run() ``` -#### Total Timeout +#### Umumiy vaqt tugashi (Total Timeout) -You can enforce a global timeout for the entire pool execution using the `Timeout` method. If the pool takes longer -than this duration, all running processes will be terminated. +Siz `Timeout` usuli yordamida butun hovuz bajarilishi uchun global vaqtni belgilashingiz mumkin. Agar hovuz bu vaqtdan ko'proq vaqt talab qilsa, barcha ishlayotgan jarayonlar to'xtatiladi. ```go facades.Process().Pool(...).Timeout(1 * time.Minute).Run() ``` -### Asynchronous Pools +### Asinxron hovuzlar -If you need to run the pool in the background while your application performs other tasks, you can use the `Start` -method instead of `Run`. This returns a `RunningPool` handle. +Agar ilovangiz boshqa vazifalarni bajarayotgan paytda hovuzni fonda ishga tushirishingiz kerak bo'lsa, `Run` o'rniga "Ishga `Start` usulidan foydalanishingiz mumkin. Bu `RunningPool` deskriptorini qaytaradi. ```go runningPool, err := facades.Process().Pool(func(pool process.Pool) { pool.Command("sleep", "5").As("long_task") }).Start() -// Check if the pool is still running +// Hovuz hali ham ishlayotganini tekshiring if runningPool.Running() { fmt.Println("Pool is active...") } -// Wait for all processes to finish and gather results +// Barcha jarayonlar tugashini kuting va natijalarni to'plang results := runningPool.Wait() ``` -#### Interacting with Running Pools +#### Running Pools bilan o'zaro aloqa -The `RunningPool` interface provides several methods to manage the active pool: +`RunningPool` interfeysi faol hovuzni boshqarishning bir nechta usullarini taqdim etadi: -- **`PIDs()`**: Returns a map of Process IDs keyed by the command name. -- **`Signal(os.Signal)`**: Sends a signal to all running processes in the pool. -- **`Stop(timeout, signal)`**: Gracefully stops all processes. -- **`Done()`**: Returns a channel that closes when the pool finishes, useful for `select` statements. +- **`PIDs()`**: Buyruq nomi bilan belgilangan jarayon identifikatorlari xaritasini qaytaradi. +- **`Signal(os.Signal)`**: Hovuzdagi barcha ishlayotgan jarayonlarga signal yuboradi. +- **`Stop(timeout, signal)`**: Barcha jarayonlarni nafislik bilan to'xtatadi. +- **`Done()`**: Hovuz tugagach yopiladigan kanalni qaytaradi, bu `select` operatorlari uchun foydali. ```go select { case <-runningPool.Done(): - // All processes finished + // Barcha jarayonlar tugadi case <-time.After(10 * time.Second): - // Force stop all processes if they take too long + // Agar barcha jarayonlar juda uzoq davom etsa, ularni majburan to'xtatish runningPool.Stop(1 * time.Second) } ``` ### Pool Output -You can inspect the output of the pool in real-time using the `OnOutput` method. +Siz `OnOutput` usuli yordamida real vaqt rejimida hovuzning chiqishini tekshirishingiz mumkin. :::warning -The `OnOutput` callback may be invoked concurrently from multiple goroutines. Ensure your callback logic is thread-safe. +`OnOutput` qayta chaqiruvi bir vaqtning o'zida bir nechta goroutinlardan chaqirilishi mumkin. Qayta qo'ng'iroq qilish mantig'ingiz ish zarrachalaridan himoyalanganligiga ishonch hosil qiling. ::: ```go facades.Process().Pool(func(pool process.Pool) { pool.Command("ping", "google.com").As("ping") }).OnOutput(func(typ process.OutputType, line []byte, key string) { - // key will be "ping" + // kalit "ping" bo'ladi fmt.Printf("[%s] %s", key, string(line)) }).Run() ``` -### Per-Process Configuration +### Jarayon bo'yicha konfiguratsiya -Inside the pool definition, each command supports individual configuration methods similar to single processes: +Hovuz ta'rifi ichida har bir buyruq yakka jarayonlarga o'xshash individual konfiguratsiya usullarini qo'llab-quvvatlaydi: -- **`Path(string)`**: Sets the working directory. -- **`Env(map[string]string)`**: Sets environment variables. -- **`Input(io.Reader)`**: Sets standard input. -- **`Timeout(time.Duration)`**: Sets a timeout for the specific command. -- **`Quietly()`**: Disables output capturing for this specific command. -- **`DisableBuffering()`**: Disables memory buffering (useful for high-volume output). +- **`Path(string)`**: Ishchi katalogni o'rnatadi. +- **`Env(map[string]string)`**: Muhit o'zgaruvchilarini o'rnatadi. +- **`Input(io.Reader)`**: Standart kiritishni o'rnatadi. +- **`Timeout(time.Duration)`**: Muayyan buyruq uchun vaqtni belgilaydi. +- **`Quietly()`**: Ushbu maxsus buyruq uchun chiqish yozib olishni o'chiradi. +- **`DisableBuffering()`**: Xotira buferlashni o'chiradi (yuqori hajmli chiqish uchun foydali). ```go facades.Process().Pool(func(pool process.Pool) { From 3ae7a114c0d19051e977d1d4a7bc64d224f4cba1 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 6 Apr 2026 14:51:55 +0800 Subject: [PATCH 104/163] New translations service-providers.md (Uzbek) [skip ci] Update translations (Uzbek) service-providers.md --- uz_UZ/architecture-concepts/service-providers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uz_UZ/architecture-concepts/service-providers.md b/uz_UZ/architecture-concepts/service-providers.md index 790987074..b92f8ee0a 100644 --- a/uz_UZ/architecture-concepts/service-providers.md +++ b/uz_UZ/architecture-concepts/service-providers.md @@ -4,7 +4,7 @@ ## Kirish -Yadro ishga tushirish operatsiyasida eng muhim narsa `ServiceProvider`ni yuklashdir. Ilovaning barcha `ServiceProvider`lari `bootstrap/providers.go` faylida sozlanadi. +The most important thing in the kernel boot operation is to load the `ServiceProvider`. Ilovaning barcha `ServiceProvider`lari `bootstrap/providers.go` faylida sozlanadi. Avvalo, yadro barcha xizmat ko'rsatuvchilarning `Register` metodini chaqiradi. Barcha xizmat ko'rsatuvchilar ro'yxatdan o'tkazilgandan so'ng, yadro barcha `ServiceProvider`larning `Boot` metodini yana chaqiradi. From 6a686286a985bfcb9c17eb8bbe5d3d2155bf28f1 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 6 Apr 2026 16:20:52 +0800 Subject: [PATCH 105/163] New translations readme.md (Uzbek) [skip ci] Update translations (Uzbek) readme.md --- uz_UZ/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uz_UZ/README.md b/uz_UZ/README.md index 42fa30f8f..a754d1c14 100644 --- a/uz_UZ/README.md +++ b/uz_UZ/README.md @@ -52,7 +52,7 @@ Namuna [https://github.com/goravel/example](https://github.com/goravel/example) | [Lokalizatsiya](https://www.goravel.dev/digging-deeper/localization.html) | Ko'p tilli tarjima va til sozlamalarini boshqarish | | [Logger](https://www.goravel.dev/the-basics/logging.html) | Ilovalarni fayllarga, konsolga yoki tashqi xizmatlarga yozish | | [Pochta](https://www.goravel.dev/digging-deeper/mail.html) | SMTP or navbatga asoslangan yetkazib berish orqali elektron pochta xabarlarini yuboring | -| [Mock](https://www.goravel.dev/testing/mock.html) | Create test mocks for facades and dependencies | +| [Mock](https://www.goravel.dev/testing/mock.html) | Fasadlar va qaramliklar uchun sinov namunalarini yarating | | [Migrate](https://www.goravel.dev/database/migrations.html) | Ma'lumotlar bazasi sxemasi o'zgarishlari uchun versiyalarni boshqarish | | [Orm](https://www.goravel.dev/orm/getting-started.html) | Ma'lumotlar bazasi operatsiyalari uchun nafis Orm amalga oshirilishi | | [Paketni Ishlab Chiqish](https://www.goravel.dev/digging-deeper/package-development.html) | Freymvork funksiyalarini kengaytirish uchun qayta ishlatiladigan paketlar yarating | From 1b5e355fda3c558fdfc4c6110249fd1e418baf24 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 6 Apr 2026 16:20:54 +0800 Subject: [PATCH 106/163] New translations service-providers.md (Uzbek) [skip ci] Update translations (Uzbek) service-providers.md --- uz_UZ/architecture-concepts/service-providers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uz_UZ/architecture-concepts/service-providers.md b/uz_UZ/architecture-concepts/service-providers.md index b92f8ee0a..98bd8917e 100644 --- a/uz_UZ/architecture-concepts/service-providers.md +++ b/uz_UZ/architecture-concepts/service-providers.md @@ -29,7 +29,7 @@ func Boot() contractsfoundation.Application { } ``` -## Dependency Relationship +## Qaramlik munosabati `ServiceProvider` `Relationship()` ixtiyoriy usulini taqdim etadi `binding.Relationship`, bog'liqlik munosabatini e'lon qilish uchun ishlatiladi, ushbu usulni o'rnatgan `ServiceProvider` ro'yxatga olish tartibiga bog'liq bo'lmaydi, va uni o'rnatmagan `ServiceProvider` oxirgi ro'yxatga olinadi, masalan: From 0cee93c1b6f9df65f1ae11881b4c9bb051f6e954 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 6 Apr 2026 16:20:55 +0800 Subject: [PATCH 107/163] New translations queries.md (Uzbek) [skip ci] Update translations (Uzbek) queries.md --- uz_UZ/database/queries.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uz_UZ/database/queries.md b/uz_UZ/database/queries.md index 41ff4acb8..371e58532 100644 --- a/uz_UZ/database/queries.md +++ b/uz_UZ/database/queries.md @@ -575,7 +575,7 @@ result, err := facades.DB().Table("products").Where("id", 1).Update(map[string]a }) ``` -### Update JSON fields +### JSON maydonlarini yangilang ```go result, err := facades.DB().Table("users").Where("id", 1).Update("options->enabled", true) From d9ebcf8a6bbf8644d542b9d4b0ec563fb5d552a8 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 6 Apr 2026 16:20:56 +0800 Subject: [PATCH 108/163] New translations filesystem.md (Uzbek) [skip ci] Update translations (Uzbek) filesystem.md --- uz_UZ/digging-deeper/filesystem.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uz_UZ/digging-deeper/filesystem.md b/uz_UZ/digging-deeper/filesystem.md index 8449eb645..d811de10a 100644 --- a/uz_UZ/digging-deeper/filesystem.md +++ b/uz_UZ/digging-deeper/filesystem.md @@ -194,7 +194,7 @@ file, err := filesystem.NewFile("./logo.png") path := facades.Storage().PutFile("photos", file) ``` -### Specifying A File Name +### Fayl nomini ko'rsatish Agar saqlangan faylingizga avtomatik ravishda fayl nomi berilmasligini istasangiz, `StoreAs` metodidan foydalanishingiz mumkin, bu metod argument sifatida yo‘l, fayl nomi va (ixtiyoriy) diskni qabul qiladi: From 8d314a55fb96b589b7c9aa23da6f349ff6a24a75 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 6 Apr 2026 16:20:58 +0800 Subject: [PATCH 109/163] New translations helpers.md (Uzbek) [skip ci] Update translations (Uzbek) helpers.md --- uz_UZ/digging-deeper/helpers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uz_UZ/digging-deeper/helpers.md b/uz_UZ/digging-deeper/helpers.md index 8f4d11021..eaa8c0822 100644 --- a/uz_UZ/digging-deeper/helpers.md +++ b/uz_UZ/digging-deeper/helpers.md @@ -737,7 +737,7 @@ collect.Split([]int{1, 2, 3, 4, 5}, 2) ### `collect.Sum()` -The `collect.Sum()` function returns the sum of all items in the collection: +`collect.Sum()` funksiyasi to'plamdagi barcha elementlarning yig'indisini qaytaradi: ```go collect.Sum([]int{1, 2, 3, 4, 5}) // 15 From cbb428e6ac17e3ba46086287947d4c783ca5e9f6 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 6 Apr 2026 16:20:59 +0800 Subject: [PATCH 110/163] New translations http-client.md (Uzbek) [skip ci] Update translations (Uzbek) http-client.md --- uz_UZ/digging-deeper/http-client.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/uz_UZ/digging-deeper/http-client.md b/uz_UZ/digging-deeper/http-client.md index 6fe28a539..ad279250d 100644 --- a/uz_UZ/digging-deeper/http-client.md +++ b/uz_UZ/digging-deeper/http-client.md @@ -208,7 +208,7 @@ response, err := facades.Http(). :::tip `WithToken` usuli shuningdek, token turini (masalan, "Bearer", "Token") belgilash uchun ixtiyoriy ikkinchi argumentni ham qabul qiladi. -If no type is provided, it defaults to "Bearer". +Agar hech qanday tur ko'rsatilmagan bo'lsa, u standart holatda "Tashiydigan" ga o'rnatiladi. ```go response, err := facades.Http(). @@ -404,15 +404,15 @@ facades.Http().AssertSent(func(req client.Request) bool { Shuningdek, ma'lum bir so'rov _yuborilmagan_ligini tasdiqlashingiz yoki yuborilgan so'rovlarning umumiy sonini tekshirishingiz mumkin: ```go -// Assert a request was NOT sent +// So'rov yuborilmaganligini tasdiqlang facades.Http().AssertNotSent(func(req client.Request) bool { - return req.Url() == "https://api.example.com/legacy-endpoint" +return req.Url() == "https://api.example.com/legacy-endpoint" }) -// Assert that no requests were sent at all +// Hech qanday so'rov yuborilmaganligini tasdiqlang facades.Http().AssertNothingSent() -// Assert that exactly 3 requests were sent +// Aynan 3 ta so'rov yuborilganligini tasdiqlang facades.Http().AssertSentCount(3) ``` From 2c1dc68c0af09f77d073a80ec43742429530530d Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 6 Apr 2026 21:52:56 +0800 Subject: [PATCH 111/163] New translations queues.md (Uzbek) [skip ci] Update translations (Uzbek) queues.md --- uz_UZ/digging-deeper/queues.md | 118 ++++++++++++++++----------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/uz_UZ/digging-deeper/queues.md b/uz_UZ/digging-deeper/queues.md index 791d13655..34adfbc3d 100644 --- a/uz_UZ/digging-deeper/queues.md +++ b/uz_UZ/digging-deeper/queues.md @@ -1,48 +1,48 @@ -# Queues +# Navbatlar [[toc]] -## Introduction +## Kirish -When building your web application, there may be tasks, like parsing and storing an uploaded CSV file, that take too long to complete during a web request. Fortunately, Goravel offers a solution by allowing you to create queued jobs that can run in the background. This way, by moving time-intensive tasks to a queue, your application can respond to web requests much faster and provide a better user experience for your customers. To implement this feature, we use `facades.Queue()`. +Veb-ilovangizni yaratishda, veb-so‘rov davomida bajarish uchun juda uzoq vaqt talab qiladigan, yuklangan CSV faylini tahlil qilish va saqlash kabi vazifalar bo‘lishi mumkin. Xo‘sh, Goravel sizga orqa fonda ishlaydigan navbatga qo‘yilgan ishlarni yaratish imkoniyatini beruvchi yechimni taklif qiladi. Shu tarzda, vaqt talab qiladigan vazifalarni navbatga o‘tkazish orqali, ilovangiz veb-so‘rovlarga ancha tezroq javob bera oladi va mijozlaringiz uchun yaxshi foydalanuvchi tajribasini taqdim etadi. Ushbu xususiyatni amalga oshirish uchun biz `facades.Queue()` dan foydalanamiz. -### Connections Vs. Queues +### Ulanishlar va Navbatlar -Before delving into Goravel queues, it's important to understand the difference between "connections" and "queues". In the configuration file, `config/queue.go`, you'll find an array for `connections` configuration. This option specifies the connections to backend queue services like Redis. However, every queue connection can have multiple "queues", which can be thought of as different stacks or piles of queued jobs. +Goravel navbatlarini chuqur o‘rganishdan oldin, "ulanishlar" va "navbatlar" o‘rtasidagi farqni tushunish muhimdir. Konfiguratsiya faylida, `config/queue.go` da, `connections` konfiguratsiyasi uchun massivni topasiz. Ushbu parametr Redis kabi orqa fondagi navbat xizmatlariga ulanishlarni belgilaydi. Biroq, har bir navbat ulanishi bir nechta "navbatlarga" ega bo‘lishi mumkin, ular navbatga qo‘yilgan ishlarning turli steklari yoki to‘plamlari deb tushunilishi mumkin. -It's essential to note that each connection configuration example in the queue configuration file includes a `queue` attribute. This attribute is the default queue to which jobs will be dispatched when they are sent to a given connection. In simpler terms, if you dispatch a job without explicitly defining which queue it should be dispatched to, the job will be placed in the queue defined in the queue attribute of the connection configuration. +Navbat konfiguratsiya faylidagi har bir ulanish konfiguratsiyasi misolida `queue` atributi mavjudligini ta‘kidlash muhimdir. Ushbu atribut, ishlar berilgan ulanishga yuborilganda ular yuboriladigan standart navbatdir. Oddiyroq qilib aytganda, agar siz ishni qaysi navbatga yuborilishi kerakligini aniq belgilamasdan yuborsangiz, ish ulanish konfiguratsiyasining queue atributida belgilangan navbatga joylashtiriladi. ```go -// This job is sent to the default connection's default queue +// Bu ish standart ulanishning standart navbatiga yuboriladi err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{ {Type: "int", Value: 1}, }).Dispatch() -// This job is sent to the default connection's "emails" queue +// Bu ish standart ulanishning "emails" navbatiga yuboriladi err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{ {Type: "int", Value: 1}, }).OnQueue("emails").Dispatch() ``` -## Driver +## Haydovchi -The queue configuration file is stored in `config/queue.go`, and different queue drivers can be set in the configuration file. +Navbat konfiguratsiya fayli `config/queue.go` da saqlanadi va konfiguratsiya faylida turli navbat haydovchilari o‘rnatilishi mumkin. -### Sync Driver +### Sinxron Haydovchi -The sync driver is the default driver, it will not push tasks to the queue, but execute directly in the current process. +Sinxron haydovchi standart haydovchidir, u vazifalarni navbatga qo‘ymaydi, balki joriy jarayonda bevosita bajaradi. -### Database Driver +### Ma'lumotlar Bazasi Haydovchisi -To use the `database` driver, you need to create a database table to store tasks first: [20210101000002_create_jobs_table.go](https://github.com/goravel/goravel/blob/master/database/migrations/20210101000002_create_jobs_table.go). The migration file is located in the `database/migrations` directory by default. +`database` haydovchisidan foydalanish uchun avval vazifalarni saqlash uchun ma'lumotlar bazasi jadvalini yaratishingiz kerak: [20210101000002_create_jobs_table.go](https://github.com/goravel/goravel/blob/master/database/migrations/20210101000002_create_jobs_table.go). Migratsiya fayli sukut bo‘yicha `database/migrations` katalogida joylashgan. -### Custom Driver +### Maxsus Haydovchi -If the current driver cannot meet your needs, you can customize the driver. You need to implement the [Driver](https://github.com/goravel/framework/blob/master/contracts/queue/driver.go#L14) interface in `contracts/queue/driver.go`. +Agar joriy haydovchi sizning ehtiyojlaringizni qondira olmasa, siz haydovchini sozlashingiz mumkin. Siz `contracts/queue/driver.go` dagi [Driver](https://github.com/goravel/framework/blob/master/contracts/queue/driver.go#L14) interfeysini amalga oshirishingiz kerak. -The official implementation of the `Redis` driver, you can refer to [Redis Driver](https://github.com/goravel/redis) to implement your own custom driver. +`Redis` drayverining rasmiy amalga oshirilishi, siz o'z maxsus drayveringizni amalga oshirish uchun [Redis Drayveri](https://github.com/goravel/redis) ga murojaat qilishingiz mumkin. -After implementing the custom driver, you can add the configuration to `config/queue.go`: +Maxsus haydovchini amalga oshirgandan so‘ng, konfiguratsiyani `config/queue.go` ga qo‘shishingiz mumkin: ``` ... @@ -52,26 +52,26 @@ After implementing the custom driver, you can add the configuration to `config/q "connection": "default", "queue": "default", "via": func() (queue.Driver, error) { - return redisfacades.Queue("redis") // The redis value is the key of connections + return redisfacades.Queue("redis") // redis qiymati connections kalitidir }, }, }, ``` -## Creating Jobs +## Ishlarni Yaratish -### Generating Job Classes +### Ish Klasslarini Yaratish -By default, all of the jobs for your application are stored in the `app/jobs` directory. If the `app/Jobs` directory doesn't exist, it will be created when you run the `make:job` Artisan command: +Sukut bo‘yicha, ilovangizning barcha ishlari `app/jobs` katalogida saqlanadi. Agar `app/Jobs` katalogi mavjud bo‘lmasa, u `make:job` Artisan buyrug‘ini ishga tushirganingizda yaratiladi: ```shell ./artisan make:job ProcessPodcast ./artisan make:job user/ProcessPodcast ``` -### Register Jobs +### Ishlarni ro'yxatdan o'tkazish -A new job created by `make:job` will be registered automatically in the `bootstrap/jobs.go::Jobs()` function and the function will be called by `WithJobs`. You need register the job manually if you create the job file by yourself. +`make:job` tomonidan yaratilgan yangi ish `bootstrap/jobs.go::Jobs()` funksiyasida avtomatik ro'yxatdan o'tkaziladi va funksiya `WithJobs` tomonidan chaqiriladi. Agar ish faylini o'zingiz yaratgan bo'lsangiz, ishni qo'lda ro'yxatdan o'tkazishingiz kerak. ```go func Boot() contractsfoundation.Application { @@ -82,9 +82,9 @@ func Boot() contractsfoundation.Application { } ``` -### Class Structure +### Klass Tuzilmasi -Job classes are very simple, consisting of two methods: `Signature` and `Handle`. `Signature` serves as a task's distinct identifier, while `Handle` executes when the queue processes the task. Additionally, the `[]queue.Arg{}` passed when the task executes will be transmitted into `Handle`: +Ish klasslari juda oddiy, ikkita usuldan iborat: `Signature` va `Handle`. `Signature` vazifaning o‘ziga xos identifikatori vazifasini bajaradi, `Handle` esa navbat vazifani qayta ishlaganda bajariladi. Bundan tashqari, vazifa bajarilganda uzatilgan `[]queue.Arg{}` `Handle` ga uzatiladi: ```go package jobs @@ -92,31 +92,31 @@ package jobs type ProcessPodcast struct { } -// Signature The name and signature of the job. +// Signature Ishning nomi va imzosi. func (r *ProcessPodcast) Signature() string { return "process_podcast" } -// Handle Execute the job. +// Handle Ishni bajarish. func (r *ProcessPodcast) Handle(args ...any) error { return nil } ``` -#### Job Retry +#### Ishni Qayta Urinish -Job classes support an optional `ShouldRetry(err error, attempt int) (retryable bool, delay time.Duration)` method, which is used to control job retry. +Ish klasslari ishni qayta urinishni boshqarish uchun ishlatiladigan ixtiyoriy `ShouldRetry(err error, attempt int) (retryable bool, delay time.Duration)` usulini qo‘llab-quvvatlaydi. ```go -// ShouldRetry determines if the job should be retried based on the error. +// ShouldRetry xatoga asoslanib, ish qayta urinib ko‘rilishini belgilaydi. func (r *ProcessPodcast) ShouldRetry(err error, attempt int) (retryable bool, delay time.Duration) { return true, 10 * time.Second } ``` -## Start Queue Server +## Navbat Serverini Ishga Tushirish -The default queue worker will be run by the runner of queue seriver provider, if you want to start multiple queue workers with different configuration, you can create [a runner](../architecture-concepts/service-providers.md#runners) and add it to the `WithRunners` function in the `bootstrap/app.go` file: +Standart navbat ishchisi navbat seriver provayderining runneri tomonidan ishga tushiriladi, agar siz turli konfiguratsiyalar bilan bir nechta navbat ishchilarini ishga tushirmoqchi bo'lsangiz, [runner](../architecture-concepts/service-providers.md#runners) yaratishingiz va uni `bootstrap/app.go` faylidagi `WithRunners` funksiyasiga qo'shishingiz mumkin: ```go func Boot() contractsfoundation.Application { @@ -131,11 +131,11 @@ func Boot() contractsfoundation.Application { } ``` -You can check [the default queue runner](https://github.com/goravel/framework/blob/master/queue/runners.go) for reference. +Siz ma'lumot uchun [standart navbat runneri](https://github.com/goravel/framework/blob/master/queue/runners.go) ni tekshirishingiz mumkin. -## Dispatching Jobs +## Ishlarni Yuborish -Once you have written the job class, you can dispatch it using the `Dispatch` method on the job itself: +Ish klassini yozganingizdan so‘ng, uni ishning o‘zidagi `Dispatch` usuli yordamida yuborishingiz mumkin: ```go package controllers @@ -159,9 +159,9 @@ func (r *UserController) Show(ctx http.Context) { } ``` -### Synchronous Dispatching +### Sinxron Yuborish -If you want to dispatch a job immediately (synchronously), you can use the `DispatchSync` method. When using this method, the job will not be queued and will be executed immediately within the current process: +Agar siz ishni darhol (sinxron ravishda) yubormoqchi bo‘lsangiz, `DispatchSync` usulidan foydalanishingiz mumkin. Ushbu usuldan foydalanganda, ish navbatga qo‘yilmaydi va joriy jarayon ichida darhol bajariladi: ```go package controllers @@ -185,9 +185,9 @@ func (r *UserController) Show(ctx http.Context) { } ``` -### Job Chaining +### Ishlar Zanjiri -Job chaining allows you to specify a list of queued jobs to be executed in a specific order. If any job in the sequence fails, the rest of the jobs will not be executed. To run a queued job chain, you can use the `Chain` method provided by the `facades.Queue()`: +Ishlar zanjiri sizga ma‘lum tartibda bajarilishi kerak bo‘lgan navbatga qo‘yilgan ishlar ro‘yxatini belgilash imkonini beradi. Agar ketma-ketlikdagi har qanday ish muvaffaqiyatsiz bo‘lsa, qolgan ishlar bajarilmaydi. Navbatga qo‘yilgan ishlar zanjirini ishga tushirish uchun `facades.Queue()` tomonidan taqdim etilgan `Chain` usulidan foydalanishingiz mumkin: ```go err := facades.Queue().Chain([]queue.Jobs{ @@ -206,71 +206,71 @@ err := facades.Queue().Chain([]queue.Jobs{ }).Dispatch() ``` -### Delayed Dispatching +### Kechiktirilgan Yuborish -If you would like to specify that a job should not be immediately processed by a queue worker, you may use the `Delay` method during job dispatch. For example, let's specify that a job should not be available for processing after 100 seconds of dispatching: +Agar siz ishning navbat ishchisi tomonidan darhol qayta ishlanmasligini belgilamoqchi bo‘lsangiz, ish yuborilayotganda `Delay` usulidan foydalanishingiz mumkin. Misol uchun, ish yuborilgandan 100 soniyadan keyin qayta ishlash uchun mavjud bo‘lmasligini belgilaymiz: ```go err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{}).Delay(time.Now().Add(100*time.Second)).Dispatch() ``` -### Customizing The Queue & Connection +### Navbat va Ulanishni Sozlash -#### Dispatching To A Particular Queue +#### Muayyan Navbatga Yuborish -By pushing jobs to different queues, you may "categorize" your queued jobs and even prioritize how many workers you assign to various queues. +Ishlarni turli navbatlarga yuborish orqali, siz navbatga qo‘yilgan ishlaringizni "toifalarga ajratishingiz" va hatto turli navbatlarga qancha ishchi tayinlash ustunligini belgilashingiz mumkin. ```go err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{}).OnQueue("processing").Dispatch() ``` -#### Dispatching To A Particular Connection +#### Muayyan Ulanishga Yuborish -If your application interacts with multiple queue connections, you can use the `OnConnection` method to specify the connection to which the task is pushed. +Agar ilovangiz bir nechta navbat ulanishlari bilan ishlayotgan bo‘lsa, vazifa qaysi ulanishga yuborilishini belgilash uchun `OnConnection` usulidan foydalanishingiz mumkin. ```go err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{}).OnConnection("sync").Dispatch() ``` -You may chain the `OnConnection` and `OnQueue` methods together to specify the connection and the queue for a job: +Siz ish uchun ulanish va navbatni belgilash uchun `OnConnection` va `OnQueue` usullarini birgalikda zanjirlashingiz mumkin: ```go err := facades.Queue().Job(&jobs.Test{}, []queue.Arg{}).OnConnection("sync").OnQueue("processing").Dispatch() ``` -## View Failed Jobs +## Muvaffaqiyatsiz Ishlarni Ko‘rish -You can use the `queue:failed` command to view failed jobs, this command will get the failed jobs from the `failed_jobs` table in the database: +Muvaffaqiyatsiz ishlarni ko‘rish uchun `queue:failed` buyrug‘idan foydalanishingiz mumkin, bu buyruq ma‘lumotlar bazasidagi `failed_jobs` jadvalidan muvaffaqiyatsiz ishlarni oladi: ```shell ./artisan queue:failed ``` -## Retrying Failed Jobs +## Muvaffaqiyatsiz Ishlarni Qayta Urinish -If a job fails during processing, you can use the `queue:retry` command to retry the job. Before retrying the job, you need to get the UUID of the job to be retried from the `failed_jobs` table in the database: +Agar ish qayta ishlash paytida muvaffaqiyatsiz bo‘lsa, ishni qayta urinish uchun `queue:retry` buyrug‘idan foydalanishingiz mumkin. Ishni qayta urinishdan oldin, ma‘lumotlar bazasidagi `failed_jobs` jadvalidan qayta urinilishi kerak bo‘lgan ishning UUID ni olishingiz kerak: ```shell -# Retry a single job +# Bitta ishni qayta urinish ./artisan queue:retry 4427387e-c75a-4295-afb3-2f3d0e410494 -# Retry multiple jobs +# Bir nechta ishlarni qayta urinish ./artisan queue:retry 4427387e-c75a-4295-afb3-2f3d0e410494 eafdd963-a8b7-4aca-9421-b376ed9f4382 -# Retry failed jobs for a specific connection +# Muayyan ulanish uchun muvaffaqiyatsiz ishlarni qayta urinish ./artisan queue:retry --connection=redis -# Retry failed jobs for a specific queue +# Muayyan navbat uchun muvaffaqiyatsiz ishlarni qayta urinish ./artisan queue:retry --queue=processing -# Retry failed jobs for a specific connection and queue +# Muayyan ulanish va navbat uchun muvaffaqiyatsiz ishlarni qayta urinish ./artisan queue:retry --connection=redis --queue=processing -# Retry all failed jobs +# Barcha muvaffaqiyatsiz ishlarni qayta urinish ./artisan queue:retry all ``` -## `queue.Arg.Type` Supported Types +## `queue.Arg.Type` Qo‘llab-quvvatlanadigan Turlar ```go bool From 196519724f7b5dbbf5905ddaa12dd210ea94515b Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 6 Apr 2026 21:52:58 +0800 Subject: [PATCH 112/163] New translations strings.md (Uzbek) [skip ci] Update translations (Uzbek) strings.md --- uz_UZ/digging-deeper/strings.md | 250 ++++++++++++++++---------------- 1 file changed, 124 insertions(+), 126 deletions(-) diff --git a/uz_UZ/digging-deeper/strings.md b/uz_UZ/digging-deeper/strings.md index 41b5a8903..dcf74c532 100644 --- a/uz_UZ/digging-deeper/strings.md +++ b/uz_UZ/digging-deeper/strings.md @@ -26,7 +26,7 @@ str.Of("Goravel") ### `After` -The `After` method returns the portion of a string that appears after a specified value. If the value is an empty string or does not exist within the original string, the full string is returned. +`After` usuli satrdagi belgilangan qiymatdan keyingi qismini qaytaradi. Agar qiymat bo'sh satr bo'lsa yoki asl satr ichida mavjud bo'lmasa, to'liq satr qaytariladi. ```go import "github.com/goravel/framework/support/str" @@ -36,7 +36,7 @@ str.Of("Hello World!").After("Hello").String() // " World!" ### `AfterLast` -The `AfterLast` method returns the portion of a string that appears after the last occurrence of a specified value. If the value is an empty string or does not exist within the original string, the full string is returned. +`AfterLast` usuli satrdagi belgilangan qiymatning oxirgi paydo bo'lishidan keyingi qismini qaytaradi. Agar qiymat bo'sh satr bo'lsa yoki asl satr ichida mavjud bo'lmasa, to'liq satr qaytariladi. ```go import "github.com/goravel/framework/support/str" @@ -46,7 +46,7 @@ str.Of("docs.goravel.dev").AfterLast(".").String() // "dev" ### `Append` -The `Append` method appends the specified value to the end of the string. +`Append` usuli belgilangan qiymatni satr oxiriga qo'shadi. ```go import "github.com/goravel/framework/support/str" @@ -56,7 +56,7 @@ str.Of("Bowen").Append(" Han").String() // "Bowen Han" ### `Basename` -The `Basename` method returns the trailing name component of a path, optionally removing a specified suffix from the base name. +`Basename` usuli yo'lning oxirgi nom komponentini qaytaradi, ixtiyoriy ravishda asosiy nomdan belgilangan qo'shimchani olib tashlaydi. ```go import "github.com/goravel/framework/support/str" @@ -68,7 +68,7 @@ str.Of("framework/support/str.go").Basename(".go").String() // "str" ### `Before` -The `Before` method returns the portion of a string that appears before a specified value. If the value is an empty string or does not exist within the original string, the full string is returned. +`Before` usuli satrdagi belgilangan qiymatdan oldingi qismini qaytaradi. Agar qiymat bo'sh satr bo'lsa yoki asl satr ichida mavjud bo'lmasa, to'liq satr qaytariladi. ```go import "github.com/goravel/framework/support/str" @@ -78,7 +78,7 @@ str.Of("Hello World!").Before("World").String() // "Hello " ### `BeforeLast` -The `BeforeLast` method returns the portion of a string that appears before the last occurrence of a specified value. If the value is an empty string or does not exist within the original string, the full string is returned. +`BeforeLast` usuli satrdagi belgilangan qiymatning oxirgi paydo bo'lishidan oldingi qismini qaytaradi. Agar qiymat bo'sh satr bo'lsa yoki asl satr ichida mavjud bo'lmasa, to'liq satr qaytariladi. ```go import "github.com/goravel/framework/support/str" @@ -88,7 +88,7 @@ str.Of("docs.goravel.dev").BeforeLast(".").String() // "docs.goravel" ### `Between` -The `Between` method returns the portion of a string between two given values. +`Between` usuli satrning berilgan ikki qiymat orasidagi qismini qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -98,7 +98,7 @@ str.Of("[Hello] World!").Between("[", "]").String() // "Hello" ### `BetweenFirst` -The `BetweenFirst` method returns the portion of a string between the first occurrence of two given values. +`BetweenFirst` usuli satrning berilgan ikki qiymatning birinchi paydo bo'lishi orasidagi qismini qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -108,7 +108,7 @@ str.Of("[Hello] [World]!").BetweenFirst("[", "]").String() // "Hello" ### `Camel` -The `Camel` method converts the string to `camelCase`. +`Camel` usuli satrni `camelCase` ga o'zgartiradi. ```go import "github.com/goravel/framework/support/str" @@ -118,7 +118,7 @@ str.Of("hello_world").Camel().String() // "helloWorld" ### `CharAt` -The `CharAt` method returns the character at the given index. If the index is out of bounds, an empty string will be returned. +`CharAt` usuli berilgan indeksdagi belgini qaytaradi. Agar indeks chegaradan tashqarida bo'lsa, bo'sh satr qaytariladi. ```go import "github.com/goravel/framework/support/str" @@ -128,7 +128,7 @@ str.Of("Goravel").CharAt(1) // "o" ### `ChopEnd` -The `ChopEnd` method removes the given value(s) from the end of the string. +`ChopEnd` usuli berilgan qiymat(lar)ni satr oxiridan olib tashlaydi. ```go import "github.com/goravel/framework/support/str" @@ -138,7 +138,7 @@ str.Of("https://goravel.com").ChopEnd(".dev", ".com").String() // https://gorave ### `ChopStart` -The `ChopStart` method removes the given value(s) from the start of the string. +`ChopStart` usuli berilgan qiymat(lar)ni satr boshidan olib tashlaydi. ```go import "github.com/goravel/framework/support/str" @@ -148,7 +148,7 @@ str.Of("https://goravel.dev").ChopStart("http://", "https://").String() // gorav ### `Contains` -The `Contains` method determines if the given string contains the given value. The method is case-sensitive. If multiple values are provided, it will return `true` if the string contains any of the values. +`Contains` usuli berilgan satr berilgan qiymatni o'z ichiga olganligini aniqlaydi. Usul registrga sezgir. Agar bir nechta qiymat berilgan bo'lsa, satr qiymatlardan birortasini o'z ichiga olsa, `true` qaytariladi. ```go import "github.com/goravel/framework/support/str" @@ -160,7 +160,7 @@ str.Of("Hello World").Contains("Gor", "Hello") // true ### `ContainsAll` -The `ContainsAll` method determines if the given string contains all of the given values. The method is case-sensitive. +`ContainsAll` usuli berilgan satr berilgan barcha qiymatlarni o'z ichiga olganligini aniqlaydi. Usul registrga sezgir. ```go import "github.com/goravel/framework/support/str" @@ -172,7 +172,7 @@ str.Of("Hello World").ContainsAll("Hello", "Gor") // false ### `Dirname` -The `Dirname` method returns the parent portion of a path. +`Dirname` usuli yo'lning ota-ona qismini qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -180,7 +180,7 @@ import "github.com/goravel/framework/support/str" str.Of("framework/support/str").Dirname().String() // "framework/support" ``` -Optionally, you may provide the directory level to trim from the path. +Ixtiyoriy ravishda, yo'ldan kesib tashlash uchun kataloq darajasini ko'rsatishingiz mumkin. ```go import "github.com/goravel/framework/support/str" @@ -190,7 +190,7 @@ str.Of("framework/support/str").Dirname(2).String() // "framework" ### `EndsWith` -The `EndsWith` method determines if the given string ends with the given value. The method is case-sensitive. +`EndsWith` usuli berilgan satr berilgan qiymat bilan tugaydiganligini aniqlaydi. Usul registrga sezgir. ```go import "github.com/goravel/framework/support/str" @@ -198,7 +198,7 @@ import "github.com/goravel/framework/support/str" str.Of("Goravel").EndsWith("vel") // true ``` -You may pass multiple values to the method to determine if the string ends with any of the values. +Satr qiymatlardan birortasi bilan tugashini aniqlash uchun usulga bir nechta qiymat o'tkazishingiz mumkin. ```go import "github.com/goravel/framework/support/str" @@ -208,7 +208,7 @@ str.Of("Goravel").EndsWith("vel", "lie") // true ### `Exactly` -The `Exactly` method determines if the given string is exactly equal to the given value. The method is case-sensitive. +`Exactly` usuli berilgan satr berilgan qiymatga ancha tengligini aniqlaydi. Usul registrga sezgir. ```go import "github.com/goravel/framework/support/str" @@ -218,7 +218,7 @@ str.Of("Goravel").Exactly("Goravel") // true ### `Except` -The `Except` method extracts an excerpt from the string that matches the first occurrence of the given value. +`Except` usuli satrdan berilgan qiymatning birinchi paydo bo'lishiga mos keladigan parchani ajratib oladi. ```go import "github.com/goravel/framework/support/str" @@ -229,7 +229,7 @@ str.Of("This is a beautiful morning"). }).String() // "...is a beautiful morn... ``` -Additionally, you may use `Omission` option to change the string that is used to indicate the excerpt. +Bundan tashqari, parchoni ko'rsatish uchun ishlatiladigan satrni o'zgartirish uchun `Omission` opsiyasidan foydalanishingiz mumkin. ```go import "github.com/goravel/framework/support/str" @@ -243,7 +243,7 @@ str.Of("This is a beautiful morning"). ### `Explode` -The `Explode` method splits the string into an array of strings using the given delimiter. +`Explode` usuli satrni berilgan ajratgich yordamida satrlar massiviga ajratadi. ```go import "github.com/goravel/framework/support/str" @@ -253,7 +253,7 @@ str.Of("Hello World").Explode(" ") // []string{"Hello", "World"} ### `Finish` -The `Finish` method ensures that the given string ends with the given value. If the string already ends with the value, it will not be added again. +`Finish` usuli berilgan satr berilgan qiymat bilan tugashiga ishonch hosil qiladi. Agar satr allaqachon qiymat bilan tugasa, u qayta qo'shilmaydi. ```go import "github.com/goravel/framework/support/str" @@ -265,7 +265,7 @@ str.Of("framework/").Finish("/").String() // "framework/" ### `Headline` -The `Headline` method converts the string to a headline. +`Headline` usuli satrni sarlavhaga o'zgartiradi. ```go import "github.com/goravel/framework/support/str" @@ -277,7 +277,7 @@ str.Of("HelloWorld").Headline().String() // "Hello World" ### `Is` -The `Is` method determines if the given string matches the given pattern. The method is case-sensitive. +`Is` usuli berilgan satr berilgan andozaga mos kelishini aniqlaydi. Usul katta-kichik harflarga sezgir. ```go import "github.com/goravel/framework/support/str" @@ -287,7 +287,7 @@ str.Of("foo123").Is("bar*", "baz*", "foo*") // true ### `IsEmpty` -The `IsEmpty` method determines if the given string is empty. +`IsEmpty` usuli berilgan satr bo‘sh ekanligini aniqlaydi. ```go import "github.com/goravel/framework/support/str" @@ -297,7 +297,7 @@ str.Of("").IsEmpty() // true ### `IsNotEmpty` -The `IsNotEmpty` method determines if the given string is not empty. +`IsNotEmpty` usuli berilgan satr bo‘sh emasligini aniqlaydi. ```go import "github.com/goravel/framework/support/str" @@ -307,7 +307,7 @@ str.Of("Goravel").IsNotEmpty() // true ### `IsAscii` -The `IsAscii` method determines if the given string contains only ASCII characters. +`IsAscii` usuli berilgan satr faqat ASCII belgilardan iborat ekanligini aniqlaydi. ```go import "github.com/goravel/framework/support/str" @@ -319,7 +319,7 @@ str.Of("你好").IsAscii() // false ### `IsSlice` -The `IsSlice` method determines if the given string is a slice. +`IsSlice` usuli berilgan satr kesim (slice) ekanligini aniqlaydi. ```go import "github.com/goravel/framework/support/str" @@ -331,7 +331,7 @@ str.Of(`{"name": "John"}`).IsSlice() // false ### `IsMap` -The `IsMap` method determines if the given string is a map. +`IsMap` usuli berilgan satr xarita (map) ekanligini aniqlaydi. ```go import "github.com/goravel/framework/support/str" @@ -343,7 +343,7 @@ str.Of(`[{"name": "John"}, {"name": "Alice"}]`).IsMap() // false ### `IsUlid` -The `IsUlid` method determines if the given string is a ULID. +`IsUlid` usuli berilgan satr ULID ekanligini aniqlaydi. ```go import "github.com/goravel/framework/support/str" @@ -355,7 +355,7 @@ str.Of("krishan").IsUlid() // false ### `IsUuid` -The `IsUuid` method determines if the given string is a UUID. +`IsUuid` usuli berilgan satr UUID ekanligini aniqlaydi. ```go import "github.com/goravel/framework/support/str" @@ -367,7 +367,7 @@ str.Of("krishan").IsUuid() // false ### `Kebab` -The `Kebab` method converts the string to `kebab-case`. +`Kebab` usuli satrni `kebab-case` ga o‘zgartiradi. ```go import "github.com/goravel/framework/support/str" @@ -377,7 +377,7 @@ str.Of("GoravelFramework").Kebab().String() // "goravel-framework" ### `LcFirst` -The `LcFirst` method converts the first character of the string to lowercase. +`LcFirst` usuli satrning birinchi belgisini kichik harfga o‘zgartiradi. ```go import "github.com/goravel/framework/support/str" @@ -387,7 +387,7 @@ str.Of("Goravel Framework").LcFirst().String() // "goravel Framework" ### `Length` -The `Length` method returns the length of the string. +`Length` usuli satr uzunligini qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -397,7 +397,7 @@ str.Of("Goravel").Length() // 7 ### `Limit` -The `Limit` method truncates the string to the given length. +`Limit` usuli satrni berilgan uzunlikka qisqartiradi. ```go import "github.com/goravel/framework/support/str" @@ -405,7 +405,7 @@ import "github.com/goravel/framework/support/str" str.Of("This is a beautiful morning").Limit(7).String() // "This is..." ``` -Optionally, you may provide the second argument to change the string that is used to indicate the truncation. +Ixtiyoriy ravishda, siz qisqartirishni ko‘rsatish uchun ishlatiladigan satrni o‘zgartirish uchun ikkinchi argumentni taqdim etishingiz mumkin. ```go import "github.com/goravel/framework/support/str" @@ -415,7 +415,7 @@ str.Of("This is a beautiful morning").Limit(7, " (****)").String() // "This is ( ### `Lower` -The `Lower` method converts the string to lowercase. +`Lower` usuli satrni kichik harflarga o‘zgartiradi. ```go import "github.com/goravel/framework/support/str" @@ -425,7 +425,7 @@ str.Of("GORAVEL").Lower().String() // "goravel" ### `LTrim` -The `LTrim` method trims the left side of the string. +`LTrim` usuli satrning chap tomonini kesib tashlaydi. ```go import "github.com/goravel/framework/support/str" @@ -437,7 +437,7 @@ str.Of("/framework/").LTrim("/").String() // "framework/" ### `Mask` -The `Mask` method masks the string with the given mask character. +`Mask` usuli satrni berilgan maska belgisi bilan yashiradi. ```go import "github.com/goravel/framework/support/str" @@ -445,7 +445,7 @@ import "github.com/goravel/framework/support/str" str.Of("krishan@email.com").Mask("*", 3).String() // "kri**************" ``` -If needed, you may provide negative number to mask method which instruct the method to begin masking from the end of the string. +Agar kerak bo‘lsa, siz maska usuliga manfiy sonni taqdim etishingiz mumkin, bu usulga satr oxiridan yashirishni boshlashni ko‘rsatadi. ```go import "github.com/goravel/framework/support/str" @@ -457,7 +457,7 @@ str.Of("krishan@email.com").Mask("*", -13).String() // "kris**************" ### `Match` -The `Match` method determines if the given string matches the given regular expression. +`Match` usuli berilgan satr berilgan oddiy ifodaga mos kelishini aniqlaydi. ```go import "github.com/goravel/framework/support/str" @@ -467,7 +467,7 @@ str.Of("This is a (test) string").Match(`\([^)]+\)`).String() // (test) ### `MatchAll` -The `MatchAll` method determines if the given string matches all of the given regular expressions. +`MatchAll` usuli berilgan satr berilgan barcha oddiy ifodalarga mos kelishini aniqlaydi. ```go import "github.com/goravel/framework/support/str" @@ -477,7 +477,7 @@ str.Of("abc123def456def").MatchAll(`\d+`) // []string{"123", "456"} ### `IsMatch` -The `IsMatch` method determines if the given string matches (any of) the given regular expression. +`IsMatch` usuli berilgan satr (har qanday) berilgan oddiy ifodaga mos kelishini aniqlaydi. ```go import "github.com/goravel/framework/support/str" @@ -487,7 +487,7 @@ str.Of("Hello, Goravel!").IsMatch(`(?i)goravel`, `goravel!(.*)`) // true ### `NewLine` -The `NewLine` method appends a newline character to the string. +`NewLine` usuli satrga yangi qator belgisini qo‘shadi. ```go import "github.com/goravel/framework/support/str" @@ -497,7 +497,7 @@ str.Of("Goravel").NewLine(2).Append("Framework").String() // "Goravel\n\nFramewo ### `PadBoth` -The `PadBoth` method pads both sides of the string. +`PadBoth` usuli satrning ikkala tomonini to‘ldiradi. ```go import "github.com/goravel/framework/support/str" @@ -507,7 +507,7 @@ str.Of("Hello").PadBoth(10, "_").String() // "__Hello___" ### `PadLeft` -The `PadLeft` method pads the left side of the string. +`PadLeft` usuli satrning chap tomonini to‘ldiradi. ```go import "github.com/goravel/framework/support/str" @@ -517,7 +517,7 @@ str.Of("Hello").PadLeft(10, "_").String() // "_____Hello" ### `PadRight` -The `PadRight` method pads the right side of the string. +`PadRight` usuli satrning o‘ng tomonini to‘ldiradi. ```go import "github.com/goravel/framework/support/str" @@ -527,7 +527,7 @@ str.Of("Hello").PadRight(10, "_").String() // "Hello_____" ### `Pipe` -The `Pipe` method allows you to transform the string using a given closure. +`Pipe` usuli satrni berilgan yopilish (closure) yordamida o‘zgartirishga imkon beradi. ```go import "github.com/goravel/framework/support/str" @@ -539,8 +539,7 @@ str.Of("Goravel").Pipe(func(s string) string { ### `Plural` -The `Plural` method converts a singular string to its plural form. This function supports any of -the languages supported by the [pluralizer](pluralization.md). +`Plural` usuli birlik shaklidagi satrni ko‘plik shakliga o‘zgartiradi. Bu funksiya [pluralizer](pluralization.md) tomonidan qo‘llab-quvvatlanadigan har qanday tilni qo‘llab-quvvatlaydi. ```go import "github.com/goravel/framework/support/str" @@ -549,7 +548,7 @@ plural := str.Of("goose").Plural().String() // "geese" ``` -You may provide an integer argument to the function to retrieve the singular or plural form of the string: +Satrning birlik yoki ko‘plik shaklini olish uchun funksiyaga butun son argumentini taqdim etishingiz mumkin: ```go import "github.com/goravel/framework/support/str" @@ -563,7 +562,7 @@ plural = str.Of("goose").Plural(1).String() ### `Prepend` -The `Prepend` method prepends the given value to the string. +`Prepend` usuli berilgan qiymatni satrning boshiga qo‘shadi. ```go import "github.com/goravel/framework/support/str" @@ -573,7 +572,7 @@ str.Of("Framework").Prepend("Goravel ").String() // "Goravel Framework" ### `Remove` -The `Remove` method removes the given value(s) from the string. +`Remove` usuli berilgan qiymat(lar)ni satrdan olib tashlaydi. ```go import "github.com/goravel/framework/support/str" @@ -583,9 +582,9 @@ str.Of("Hello World").Remove("World").String() // "Hello " str.Of("Hello World").Remove("World", "Hello").String() // " " ``` -### `Repeat` +### `Takrorlash` -The `Repeat` method repeats the string a given number of times. +`Takrorlash` metodi matnni berilgan son marta takrorlaydi. ```go import "github.com/goravel/framework/support/str" @@ -593,9 +592,9 @@ import "github.com/goravel/framework/support/str" str.Of("a").Repeat(2).String() // "aa" ``` -### `Replace` +### `Almashtirish` -The `Replace` method replaces the given value in the string. +`Almashtirish` metodi matndagi berilgan qiymatni almashtiradi. ```go import "github.com/goravel/framework/support/str" @@ -603,7 +602,7 @@ import "github.com/goravel/framework/support/str" str.Of("Hello World").Replace("World", "Krishan").String() // "Hello Krishan" ``` -By default, the `Replace` method is case-sensitive. If you would like the method to be case-insensitive, you may pass `false` as the third argument. +Sukut boʻyicha, `Almashtirish` metodi katta-kichik harflarga sezgir. Agar metod katta-kichik harflarga sezgir boʻlmasligini xohlasangiz, uchinchi argument sifatida `false` ni oʻtkazishingiz mumkin. ```go import "github.com/goravel/framework/support/str" @@ -611,9 +610,9 @@ import "github.com/goravel/framework/support/str" str.Of("Hello World").Replace("world", "Krishan", false).String() // "Hello Krishan" ``` -### `ReplaceEnd` +### `Oxirini almashtirish` -The `ReplaceEnd` method replaces the last occurrence of the given value in the string only if it is at the end of the string. +`Oxirini almashtirish` metodi matndagi berilgan qiymatning oxirgi takrorlanishini faqat matn oxirida boʻlsa almashtiradi. ```go import "github.com/goravel/framework/support/str" @@ -623,9 +622,9 @@ str.Of("Hello World").ReplaceEnd("World", "Goravel").String() // "Hello Goravel" str.Of("Hello World").ReplaceEnd("Hello", "Goravel").String() // "Hello World" ``` -### `ReplaceFirst` +### `Birinchi takrorlanishni almashtirish` -The `ReplaceFirst` method replaces the first occurrence of the given value in the string. +`Birinchi takrorlanishni almashtirish` metodi matndagi berilgan qiymatning birinchi takrorlanishini almashtiradi. ```go import "github.com/goravel/framework/support/str" @@ -633,9 +632,9 @@ import "github.com/goravel/framework/support/str" str.Of("Hello World").ReplaceFirst("World", "Goravel").String() // "Hello Goravel" ``` -### `ReplaceLast` +### `Oxirgi takrorlanishni almashtirish` -The `ReplaceLast` method replaces the last occurrence of the given value in the string. +`Oxirgi takrorlanishni almashtirish` metodi matndagi berilgan qiymatning oxirgi takrorlanishini almashtiradi. ```go import "github.com/goravel/framework/support/str" @@ -643,9 +642,9 @@ import "github.com/goravel/framework/support/str" str.Of("Hello World").ReplaceLast("World", "Goravel").String() // "Hello Goravel" ``` -### `ReplaceMatches` +### `Moslamalarni almashtirish` -The `ReplaceMatches` method replaces the given regular expression matches in the string. +`Moslamalarni almashtirish` metodi matndagi berilgan oddiy ifoda moslamalarini almashtiradi. ```go import "github.com/goravel/framework/support/str" @@ -653,9 +652,9 @@ import "github.com/goravel/framework/support/str" str.Of("Hello, Goravel!").ReplaceMatches(`goravel!(.*)`, "Krishan") // "Hello, Krishan!" ``` -### `ReplaceStart` +### `Boshini almashtirish` -The `ReplaceStart` method replaces the first occurrence of the given value in the string only if it is at the start of the string. +`Boshini almashtirish` metodi matndagi berilgan qiymatning birinchi takrorlanishini faqat matn boshida boʻlsa almashtiradi. ```go import "github.com/goravel/framework/support/str" @@ -665,9 +664,9 @@ str.Of("Hello World").ReplaceStart("Hello", "Goravel").String() // "Goravel Worl str.Of("Hello World").ReplaceStart("World", "Goravel").String() // "Hello World" ``` -### `RTrim` +### `Oʻng tomondan kesish` -The `RTrim` method trims the right side of the string. +`Oʻng tomondan kesish` metodi matnning oʻng tomonini kesadi. ```go import "github.com/goravel/framework/support/str" @@ -679,8 +678,7 @@ str.Of("/framework/").RTrim("/").String() // "/framework" ### `Singular` -The `Singular` method converts a string to its singular form. This function supports any of -the languages supported by the [pluralizer](pluralization.md). +`Singular` usuli satrni uning birlik shakliga o‘zgartiradi. Bu funksiya [pluralizer](pluralization.md) tomonidan qo‘llab-quvvatlanadigan har qanday tilni qo‘llab-quvvatlaydi. ```go import "github.com/goravel/framework/support/str" @@ -689,9 +687,9 @@ singular := str.Of("heroes").Singular().String() // "hero" ``` -### `Snake` +### `Iloncha` -The `Snake` method converts the string to `snake_case`. +`Iloncha` metodi matnni `iloncha_kichik` formatiga oʻtkazadi. ```go import "github.com/goravel/framework/support/str" @@ -699,9 +697,9 @@ import "github.com/goravel/framework/support/str" str.Of("GoravelFramework").Snake().String() // "goravel_framework" ``` -### `Split` +### `Ajratish` -The `Split` method splits the string into an array of strings using the given delimiter. +`Ajratish` metodi matnni berilgan ajratgich yordamida matnlar massiviga ajratadi. ```go import "github.com/goravel/framework/support/str" @@ -709,9 +707,9 @@ import "github.com/goravel/framework/support/str" str.Of("Hello World").Split(" ") // []string{"Hello", "World"} ``` -### `Squish` +### `Siquvchan` -The `Squish` method replaces consecutive whitespace characters with a single space. +`Siquvchan` metodi ketma-ket boʻsh joy belgilarini bitta boʻsh joy bilan almashtiradi. ```go import "github.com/goravel/framework/support/str" @@ -719,9 +717,9 @@ import "github.com/goravel/framework/support/str" str.Of("Hello World").Squish().String() // "Hello World" ``` -### `Start` +### `Boshlash` -The `Start` method adds a single instance of the given value to the beginning of the string if it does not already start with the value. +`Boshlash` metodi matn allaqachon berilgan qiymat bilan boshlanmasa, uning boshiga berilgan qiymatning bitta nusxasini qoʻshadi. ```go import "github.com/goravel/framework/support/str" @@ -731,9 +729,9 @@ str.Of("framework").Start("/").String() // "/framework" str.Of("/framework").Start("/").String() // "/framework" ``` -### `StartsWith` +### `Bilan boshlanadi` -The `StartsWith` method determines if the given string starts with (any) given value(s). The method is case-sensitive. +`Bilan boshlanadi` metodi berilgan matn (har qanday) berilgan qiymat(lar) bilan boshlanadimi yoki yoʻqligini aniqlaydi. Metod katta-kichik harflarga sezgir. ```go import "github.com/goravel/framework/support/str" @@ -743,9 +741,9 @@ str.Of("Goravel").StartsWith("Gor") // true str.Of("Hello World").StartsWith("Gor", "Hello") // true ``` -### `String` +### `Matn` -The `String` method returns the string. +`Matn` metodi matnni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -753,9 +751,9 @@ import "github.com/goravel/framework/support/str" str.Of("Goravel").String() // "Goravel" ``` -### `Studly` +### `Studli` -The `Studly` method converts the string to `StudlyCase`. +`Studli` metodi matnni `StudliKatta` formatiga oʻtkazadi. ```go import "github.com/goravel/framework/support/str" @@ -763,9 +761,9 @@ import "github.com/goravel/framework/support/str" str.Of("goravel_framework").Studly().String() // "GoravelFramework" ``` -### `Substr` +### `Kesma` -The `Substr` method returns the portion of the string starting at the given index and continuing for the given length. +`Kesma` metodi matnning berilgan indeksdan boshlab berilgan uzunlikdagi qismini qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -773,9 +771,9 @@ import "github.com/goravel/framework/support/str" str.Of("Goravel").Substr(1, 3) // "ora" ``` -### `Swap` +### `Almashtir` -The `Swap` method swaps multiple values in the string. +`Almashtir` metodi matndagi bir nechta qiymatlarni almashtiradi. ```go import "github.com/goravel/framework/support/str" @@ -786,9 +784,9 @@ str.Of("Golang is awesome").Swap(map[string]string{ }).String() // "Go is excellent" ``` -### `Tap` +### `Tepish` -The `Tap` method passes the string to the given closure and returns the string. +`Tepish` metodi matnni berilgan yopiq funksiyaga oʻtkazadi va matnni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -800,7 +798,7 @@ str.Of("Goravel").Tap(func(s string) { ### `Test` -The `Test` method determines if the given string matches the given regular expression. +`Test` metodi berilgan matn berilgan oddiy ifodaga mos keladimi yoki yoʻqligini aniqlaydi. ```go import "github.com/goravel/framework/support/str" @@ -808,9 +806,9 @@ import "github.com/goravel/framework/support/str" str.Of("Hello, Goravel!").Test(`goravel!(.*)`) // true ``` -### `Title` +### `Sarlavha` -The `Title` method converts the string to `Title Case`. +`Sarlavha` metodi matnni `Sarlavha Katta` formatiga oʻtkazadi. ```go import "github.com/goravel/framework/support/str" @@ -818,9 +816,9 @@ import "github.com/goravel/framework/support/str" str.Of("goravel framework").Title().String() // "Goravel Framework" ``` -### `Trim` +### `Kesish` -The `Trim` method trims the string. +`Kesish` metodi matnni kesadi. ```go import "github.com/goravel/framework/support/str" @@ -830,9 +828,9 @@ str.Of(" Goravel ").Trim().String() // "Goravel" str.Of("/framework/").Trim("/").String() // "framework" ``` -### `UcFirst` +### `Birinchi harfni katta` -The `UcFirst` method converts the first character of the string to uppercase. +`Birinchi harfni katta` metodi matnning birinchi belgisini katta harfga oʻtkazadi. ```go import "github.com/goravel/framework/support/str" @@ -840,9 +838,9 @@ import "github.com/goravel/framework/support/str" str.Of("goravel framework").UcFirst().String() // "Goravel framework" ``` -### `UcSplit` +### `Katta harflar bilan ajratish` -The `UcSplit` method splits the string into an array of strings using uppercase characters. +`Katta harflar bilan ajratish` metodi matnni katta harflar yordamida matnlar massiviga ajratadi. ```go import "github.com/goravel/framework/support/str" @@ -850,9 +848,9 @@ import "github.com/goravel/framework/support/str" str.Of("GoravelFramework").UcSplit() // []string{"Goravel", "Framework"} ``` -### `Unless` +### `Agar boʻlmasa` -The `Unless` method passes the string to the given closure and returns the string if the given condition is `false`. +`Agar boʻlmasa` metodi matnni berilgan yopiq funksiyaga oʻtkazadi va agar berilgan shart `false` boʻlsa, matnni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -864,9 +862,9 @@ str.Of("Goravel").Unless(func(s *String) bool { }).String() // "Fallback Applied" ``` -### `Upper` +### `Katta` -The `Upper` method converts the string to uppercase. +`Katta` metodi matnni katta harflarga oʻtkazadi. ```go import "github.com/goravel/framework/support/str" @@ -874,9 +872,9 @@ import "github.com/goravel/framework/support/str" str.Of("goravel").Upper().String() // "GORAVEL" ``` -### `When` +### `Qachonki` -The `When` method passes the string to the given closure and returns the string if the given condition is `true`. +`When` usuli satrni berilgan yopilishga uzatadi va agar berilgan shart `true` bo‘lsa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -886,11 +884,11 @@ str.Of("Bowen").When(true, func(s *str.String) *str.String { }).String() // "Bowen Han" ``` -If necessary, you may provide the third argument to the `When` method which is a closure that will be executed when the condition is `false`. +Agar kerak bo‘lsa, `When` usuliga uchinchi argument sifatida yopilishni taqdim etishingiz mumkin, u shart `false` bo‘lganda bajariladi. ### `WhenContains` -The `WhenContains` method passes the string to the given closure and returns the string if the given string contains the given value. +`WhenContains` usuli satrni berilgan yopilishga uzatadi va agar berilgan satr berilgan qiymatni o‘z ichiga olsa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -900,11 +898,11 @@ str.Of("Hello Bowen").WhenContains("Hello", func(s *str.String) *str.String { }).String() // "Hello Bowen Han" ``` -If necessary, you may provide the third argument to the `WhenContains` method which is a closure that will be executed when the string does not contain the given value. +Agar kerak bo‘lsa, `WhenContains` usuliga uchinchi argument sifatida yopilishni taqdim etishingiz mumkin, u satr berilgan qiymatni o‘z ichiga olmaganda bajariladi. ### `WhenContainsAll` -The `WhenContainsAll` method passes the string to the given closure and returns the string if the given string contains all of the given values. +`WhenContainsAll` usuli satrni berilgan yopilishga uzatadi va agar berilgan satr berilgan barcha qiymatlarni o‘z ichiga olsa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -914,11 +912,11 @@ str.Of("Hello Bowen").WhenContainsAll([]string{"Hello", "Bowen"}, func(s *str.St }).String() // "Hello Bowen Han" ``` -If necessary, you may provide the third argument to the `WhenContainsAll` method which is a closure that will be executed when the string does not contain all the given values. +Agar kerak bo‘lsa, `WhenContainsAll` usuliga uchinchi argument sifatida yopilishni taqdim etishingiz mumkin, u satr berilgan barcha qiymatlarni o‘z ichiga olmaganda bajariladi. ### `WhenEmpty` -The `WhenEmpty` method passes the string to the given closure and returns the string if the given string is empty. +`WhenEmpty` usuli satrni berilgan yopilishga uzatadi va agar berilgan satr bo‘sh bo‘lsa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -930,7 +928,7 @@ str.Of("").WhenEmpty(func(s *str.String) *str.String { ### `WhenIsAscii` -The `WhenIsAscii` method passes the string to the given closure and returns the string if the given string contains only ASCII characters. +`WhenIsAscii` usuli satrni berilgan yopilishga uzatadi va agar berilgan satr faqat ASCII belgilardan iborat bo‘lsa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -946,7 +944,7 @@ str.Of("你好").WhenIsAscii(func(s *str.String) *str.String { ### `WhenNotEmpty` -The `WhenNotEmpty` method passes the string to the given closure and returns the string if the given string is not empty. +`WhenNotEmpty` usuli satrni berilgan yopilishga uzatadi va agar berilgan satr bo‘sh bo‘lmasa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -958,7 +956,7 @@ str.Of("Goravel").WhenNotEmpty(func(s *str.String) *str.String { ### `WhenStartsWith` -The `WhenStartsWith` method passes the string to the given closure and returns the string if the given string starts with the given value. +`WhenStartsWith` usuli satrni berilgan yopilishga uzatadi va agar berilgan satr berilgan qiymat bilan boshlansa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -970,7 +968,7 @@ str.Of("hello world").WhenStartsWith("hello", func(s *str.String) *str.String { ### `WhenEndsWith` -The `WhenEndsWith` method passes the string to the given closure and returns the string if the given string ends with the given value. +`WhenEndsWith` usuli satrni berilgan yopilishga uzatadi va agar berilgan satr berilgan qiymat bilan tugasa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -982,7 +980,7 @@ str.Of("hello world").WhenEndsWith("world", func(s *str.String) *str.String { ### `WhenExactly` -The `WhenExactly` method passes the string to the given closure and returns the string if the given string is exactly equal to the given value. +`WhenExactly` usuli satrni berilgan yopilishga uzatadi va agar berilgan satr berilgan qiymatga aniq teng bo‘lsa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -994,7 +992,7 @@ str.Of("Goravel").WhenExactly("Goravel", func(s *str.String) *str.String { ### `WhenNotExactly` -The `WhenNotExactly` method passes the string to the given closure and returns the string if the given string is not exactly equal to the given value. +`WhenNotExactly` usuli satrni berilgan yopilishga uzatadi va agar berilgan satr berilgan qiymatga aniq teng bo‘lmasa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -1006,7 +1004,7 @@ str.Of("Goravel").WhenNotExactly("Goravel", func(s *str.String) *str.String { ### `WhenIs` -The `WhenIs` method passes the string to the given closure and returns the string if the given string matches the given pattern. +`WhenIs` usuli satrni berilgan yopilishga uzatadi va agar berilgan satr berilgan andozaga mos kelsa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -1018,7 +1016,7 @@ str.Of("foo/bar").WhenIs("foo/*", func(s *str.String) *str.String { ### `WhenIsUlid` -The `WhenIsUlid` method passes the string to the given closure and returns the string if the given string is a ULID. +`WhenIsUlid` usuli satrni berilgan yopilishga uzatadi va agar berilgan satr ULID bo‘lsa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -1030,7 +1028,7 @@ str.Of("01E5Z6Z1Z6Z1Z6Z1Z6Z1Z6Z1Z6").WhenIsUlid(func(s *str.String) *str.String ### `WhenIsUuid` -The `WhenIsUuid` method passes the string to the given closure and returns the string if the given string is a UUID. +`WhenIsUuid` usuli satrni berilgan yopilishga uzatadi va agar berilgan satr UUID bo‘lsa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -1042,7 +1040,7 @@ str.Of("550e8400-e29b-41d4-a716-446655440000").WhenIsUuid(func(s *str.String) *s ### `WhenTest` -The `WhenTest` method passes the string to the given closure and returns the string if the given string matches the given regular expression. +`WhenTest` usuli satrni berilgan yopilishga uzatadi va agar berilgan satr berilgan muntazam ifodaga mos kelsa, satrni qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -1054,7 +1052,7 @@ str.Of("goravel framework").WhenTest(`goravel(.*)`, func(s *str.String) *str.Str ### `WordCount` -The `WordCount` method returns the number of words in the string. +`WordCount` usuli satrdagi so‘zlar sonini qaytaradi. ```go import "github.com/goravel/framework/support/str" @@ -1064,7 +1062,7 @@ str.Of("Hello, World!").WordCount() // 2 ### `Words` -The `Words` method limits the number of words in the string. If necessary, you may provide the second argument to change the string that is used to indicate the truncation. +`Words` usuli satrdagi so‘zlar sonini cheklaydi. Agar kerak bo‘lsa, ikkinchi argument sifatida qisqartirishni ko‘rsatish uchun ishlatiladigan satrni o‘zgartirish mumkin. ```go import "github.com/goravel/framework/support/str" From a4af9ad3e6994dd3272b7e269431a99f3e06cdb0 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 6 Apr 2026 21:52:59 +0800 Subject: [PATCH 113/163] New translations task-scheduling.md (Uzbek) [skip ci] Update translations (Uzbek) task-scheduling.md --- uz_UZ/digging-deeper/task-scheduling.md | 150 ++++++++++++------------ 1 file changed, 75 insertions(+), 75 deletions(-) diff --git a/uz_UZ/digging-deeper/task-scheduling.md b/uz_UZ/digging-deeper/task-scheduling.md index 1a144fd63..b2a4c7505 100644 --- a/uz_UZ/digging-deeper/task-scheduling.md +++ b/uz_UZ/digging-deeper/task-scheduling.md @@ -1,16 +1,16 @@ -# Task Scheduling +# Vazifa rejalashtirish [[toc]] -## Introduction +## Kirish -In the past, you might need to create a cron configuration entry for each task that needed scheduling on your server. However, this approach can quickly become a pain as your task schedule is not in source control, and you have to SSH into your server to view or add/edit cron entries. +Avvalroq, serveringizda rejalashtirilishi kerak bo‘lgan har bir vazifa uchun cron konfiguratsiyasi yozuvini yaratishingiz kerak edi. Biroq, bu yondashuv tezda muammoga aylanadi, chunki vazifa jadvalingiz manba nazoratida emas va cron yozuvlarini ko‘rish yoki qo‘shish/o‘zgartirish uchun serveringizga SSH orqali ulanishingiz kerak. -Goravel's command scheduler offers a fresh approach to managing scheduled tasks on your server. With the scheduler, you can easily and clearly define your command schedule within your Goravel application. Using the scheduler, you only need to create a single cron entry on your server. +Goravelning buyruq rejalashtiruvchisi serveringizda rejalashtirilgan vazifalarni boshqarishning yangi yondashuvini taklif etadi. Rejalashtiruvchi yordamida Goravel ilovangiz ichida o‘z buyruq jadvalingizni osongina va aniq belgilashingiz mumkin. Rejalashtiruvchidan foydalangan holda, serveringizda faqat bitta cron yozuvini yaratishingiz kifoya. -## Defining Schedules +## Jadvallarni belgilash -To schedule tasks for your application, you can define them in the `WithSchedule` function in the `bootstrap/app.go` file. Let's consider an example to understand this better. In this case, we want to schedule a closure that will run every day at midnight. Inside this closure, we will execute a database query to clear a table: +Ilovingiz uchun vazifalarni rejalashtirish uchun ularni `bootstrap/app.go` faylidagi `WithSchedule` funksiyasida aniqlashingiz mumkin. Buni yaxshiroq tushunish uchun bir misolni ko‘rib chiqaylik. Bu holda, har kuni yarim tunda ishlaydigan yopilishni rejalashtirmoqchimiz. Ushbu yopilish ichida jadvalni tozalash uchun maʼlumotlar bazasi so‘rovini bajaramiz: ```go func Boot() contractsfoundation.Application { @@ -27,91 +27,91 @@ func Boot() contractsfoundation.Application { } ``` -### Scheduling Artisan Commands +### Artisan buyruqlarini rejalashtirish -In addition to scheduling closures, you can also schedule [Artisan commands](./artisan-console.md). For example, you may use the `Command` method to schedule an Artisan command using either the command's name or class. +Yopilishlarni rejalashtirishdan tashqari, siz [Artisan buyruqlarini](./artisan-console.md) ham rejalashtirishingiz mumkin. Misol uchun, Artisan buyrug‘ini uning nomi yoki sinfi yordamida rejalashtirish uchun `Command` usulidan foydalanishingiz mumkin. ```go facades.Schedule().Command("send:emails name").Daily(), ``` -### Logging Level - -When `app.debug` is `true`, the console will print all logs. Otherwise, only `error` level logs will be printed. - -### Schedule Frequency Options - -We've already seen a few examples of how you may configure a task to run at specified intervals. However, there are many more task schedule frequencies avaibable to assign to tasks: - -| 方法 | 描述 | -| ------------------------ | --------------------------------------------------- | -| `.Cron("* * * * *")` | Custom Crone schedule (minutes) | -| `.Cron("* * * * * *")` | Custom Crone schedule (seconds) | -| `.EverySecond()` | Run the task every second | -| `.EveryTwoSeconds()` | Run the task every two seconds | -| `.EveryFiveSeconds()` | Run the task every five seconds | -| `.EveryTenSeconds()` | Run the task every ten seconds | -| `.EveryFifteenSeconds()` | Run the task every fifteen seconds | -| `.EveryTwentySeconds()` | Run the task every twenty seconds | -| `.EveryThirtySeconds()` | Run the task every thirty seconds | -| `.EveryMinute()` | Run the task every minute | -| `.EveryTwoMinutes()` | Run the task every two minutes | -| `.EveryThreeMinutes()` | Run the task every three minutes | -| `.EveryFourMinutes()` | Run the task every four minutes | -| `.EveryFiveMinutes()` | Run the task every five minutes | -| `.EveryTenMinutes()` | Run the task every ten minutes | -| `.EveryFifteenMinutes()` | Run the task every fifteen minutes | -| `.EveryThirtyMinutes()` | Run the task every thirty minutes | -| `.Hourly()` | Run the task every hour | -| `.HourlyAt(17)` | Run the task every hour at 17 minutes past the hour | -| `.EveryTwoHours()` | Run the task every two hours | -| `.EveryThreeHours()` | Run the task every three hours | -| `.EveryFourHours()` | Run the task every four hours | -| `.EverySixHours()` | Run the task every six hours | -| `.Daily()` | Run the task every day at midnight | -| `.DailyAt("13:00")` | Run the task every day at 13:00 | -| `.Days(1, 3, 5)` | Run the task every Monday, Wednesday, and Friday | -| `.Weekdays()` | Run the task every Monday to Friday | -| `.Weekends()` | Run the task every Saturday and Sunday | -| `.Mondays()` | Run the task every Monday | -| `.Tuesdays()` | Run the task every Tuesday | -| `.Wednesdays()` | Run the task every Wednesday | -| `.Thursdays()` | Run the task every Thursday | -| `.Fridays()` | Run the task every Friday | -| `.Saturdays()` | Run the task every Saturday | -| `.Sundays()` | Run the task every Sunday | -| `.Weekly()` | Run the task every week | -| `.Monthly()` | Run the task every month | -| `.Quarterly()` | Run the task every quarter | -| `.Yearly()` | Run the task every year | - -### Preventing Task Overlaps - -By default, scheduled tasks will continue to run even if a previous instance is still running. To prevent this, use the following methods: - -| 方法 | 描述 | -| ------------------------ | ---------------------- | -| `.SkipIfStillRunning()` | Skip if still running | -| `.DelayIfStillRunning()` | Delay if still running | +### Jurnal darajasi + +`app.debug` `true` bo‘lganda, konsol barcha jurnallarni chop etadi. Aks holda, faqat `error` darajasidagi jurnallar chop etiladi. + +### Jadval chastotasi variantlari + +Biz vazifani belgilangan oraliqlarda qanday sozlashingiz mumkinligining bir nechta misollarini ko‘rdik. Biroq, vazifalarga tayinlash uchun mavjud bo‘lgan yana ko‘plab vazifa jadvali chastotalari mavjud: + +| Usul | Tavsif | +| ------------------------ | ----------------------------------------------------------------- | +| `.Cron("* * * * *")` | Maxsus Cron jadvali (daqiqalar) | +| `.Cron("* * * * * *")` | Maxsus Cron jadvali (soniyalar) | +| `.EverySecond()` | Vazifani har soniyada ishga tushirish | +| `.EveryTwoSeconds()` | Vazifani har ikki soniyada ishga tushirish | +| `.EveryFiveSeconds()` | Vazifani har besh soniyada ishga tushirish | +| `.EveryTenSeconds()` | Vazifani har o‘n soniyada ishga tushirish | +| `.EveryFifteenSeconds()` | Vazifani har o‘n besh soniyada ishga tushirish | +| `.EveryTwentySeconds()` | Vazifani har yigirma soniyada ishga tushirish | +| `.EveryThirtySeconds()` | Vazifani har o‘ttiz soniyada ishga tushirish | +| `.EveryMinute()` | Vazifani har daqiqada ishga tushirish | +| `.EveryTwoMinutes()` | Vazifani har ikki daqiqada ishga tushirish | +| `.EveryThreeMinutes()` | Vazifani har uch daqiqada ishga tushirish | +| `.EveryFourMinutes()` | Vazifani har to‘rt daqiqada ishga tushirish | +| `.EveryFiveMinutes()` | Vazifani har besh daqiqada ishga tushirish | +| `.EveryTenMinutes()` | Vazifani har o‘n daqiqada ishga tushirish | +| `.EveryFifteenMinutes()` | Vazifani har o‘n besh daqiqada ishga tushirish | +| `.EveryThirtyMinutes()` | Vazifani har o‘ttiz daqiqada ishga tushirish | +| `.Hourly()` | Vazifani har soatda ishga tushirish | +| `.HourlyAt(17)` | Vazifani har soatda, soatdan 17 daqiqa o‘tgach ishga tushirish | +| `.EveryTwoHours()` | Vazifani har ikki soatda ishga tushirish | +| `.EveryThreeHours()` | Vazifani har uch soatda ishga tushirish | +| `.EveryFourHours()` | Vazifani har to‘rt soatda ishga tushirish | +| `.EverySixHours()` | Vazifani har olti soatda ishga tushirish | +| `.Daily()` | Vazifani har kuni yarim tunda ishga tushirish | +| `.DailyAt("13:00")` | Vazifani har kuni soat 13:00 da ishga tushirish | +| `.Days(1, 3, 5)` | Vazifani har Dushanba, Chorshanba va Juma kunlari ishga tushirish | +| `.Weekdays()` | Vazifani har Dushanbadan Jumagacha ishga tushirish | +| `.Weekends()` | Vazifani har Shanba va Yakshanba kunlari ishga tushirish | +| `.Mondays()` | Vazifani har Dushanba kuni ishga tushirish | +| `.Tuesdays()` | Vazifani har Seshanba kuni ishga tushirish | +| `.Wednesdays()` | Vazifani har Chorshanba kuni ishga tushirish | +| `.Thursdays()` | Vazifani har Payshanba kuni ishga tushirish | +| `.Fridays()` | Vazifani har Juma kuni ishga tushirish | +| `.Saturdays()` | Vazifani har shanba kuni bajarish | +| `.Sundays()` | Vazifani har yakshanba kuni bajarish | +| `.Weekly()` | Vazifani har hafta bajarish | +| `.Monthly()` | Vazifani har oy bajarish | +| `.Quarterly()` | Vazifani har chorakda bajarish | +| `.Yearly()` | Vazifani har yil bajarish | + +### Vazifalarning Ustma-ust Kelishining Oldini Olish + +Sukut bo‘yicha, rejalashtirilgan vazifalar oldingi nusxasi hali ishlayotgan bo‘lsa ham bajarilishda davom etadi. Buning oldini olish uchun quyidagi usullardan foydalaning: + +| Usul | Tavsif | +| ------------------------ | ----------------------------------------------- | +| `.SkipIfStillRunning()` | Agar hali ishlayotgan bo‘lsa, o‘tkazib yuborish | +| `.DelayIfStillRunning()` | Agar hali ishlayotgan bo‘lsa, kechiktirish | ```go facades.Schedule().Command("send:emails name").EveryMinute().SkipIfStillRunning() facades.Schedule().Command("send:emails name").EveryMinute().DelayIfStillRunning() ``` -### Running Tasks On One Server +### Vazifalarni Bitta Serverda Bajarish -> To utilize this feature, your application must be using the memcached, dynamodb, or redis cache driver as the default cache driver. In addition, all servers must be communicating with the same central cache server. +> Ushbu xususiyatdan foydalanish uchun ilovangiz sukut bo‘yicha kesha haydovchisi sifatida memcached, dynamodb yoki redis kesha haydovchisidan foydalanishi kerak. Bundan tashqari, barcha serverlar bir markaziy kesha serveri bilan aloqa qilishi kerak. -If your application's scheduler runs on multiple servers, you can ensure that a scheduled job is executed on only one of them. For example, let's say you have a scheduled task that generates a new report every Friday night. If the task scheduler runs on three worker servers, the scheduled task will run on all three servers and create the report three times. This is not ideal! +Agar ilovangizning rejalashtiruvchisi bir nechta serverlarda ishlayotgan bo‘lsa, rejalashtirilgan ish faqat bitta serverda bajarilishini taʼminlashingiz mumkin. Misol uchun, har juma kechasi yangi hisobot yaratadigan rejalashtirilgan vazifangiz bor deb faraz qilaylik. Agar vazifa rejalashtiruvchisi uchta ishchi serverda ishlayotgan bo‘lsa, rejalashtirilgan vazifa barcha uchta serverda ishlaydi va hisobotni uch marta yaratadi. Bu maqbul emas! -To prevent this, use the `OnOneServer` method when defining the scheduled task, which will make sure that the task runs on only one server. The first server to receive the task will secure an atomic lock on the job, preventing other servers from executing the same task at the same time: +Buning oldini olish uchun rejalashtirilgan vazifani aniqlashda `OnOneServer` usulidan foydalaning, bu vazifaning faqat bitta serverda ishlashini taʼminlaydi. Vazifani qabul qilgan birinchi server ish bo‘yicha atomik qulfni oladi, bu boshqa serverlarning bir vaqtning o‘zida bir xil vazifani bajarishiga to‘sqinlik qiladi: ```go facades.Schedule().Command("report:generate").Daily().OnOneServer() ``` -Scheduled closures must be assigned a name if they are intended to be run on one server: +Agar yopilishlar bitta serverda bajarilishi kerak bo‘lsa, ularga nom berilishi kerak: ```go facades.Schedule().Call(func() { @@ -119,17 +119,17 @@ facades.Schedule().Call(func() { }).Daily().OnOneServer().Name("goravel") ``` -## Running The Scheduler +## Rejalashtiruvchini Ishga Tushirish -The scheduler will be run automatically when calling `Start()` in the `main.go` file. You can also run tasks manually : +Rejalashtiruvchi `main.go` faylida `Start()` chaqirilganda avtomatik ravishda ishga tushiriladi. Shuningdek, vazifalarni qo‘lda ishga tushirishingiz mumkin: ```shell ./artisan schedule:run ``` -## View All Tasks +## Barcha Vazifalarni Ko‘rish -You can use the `schedule:list` command to view all tasks: +Barcha vazifalarni ko‘rish uchun `schedule:list` buyrug‘idan foydalanishingiz mumkin: ```shell ./artisan schedule:list From 55acc1f1e205e736a8223c8053b3aa12e02045cc Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 6 Apr 2026 21:53:00 +0800 Subject: [PATCH 114/163] New translations compile.md (Uzbek) [skip ci] Update translations (Uzbek) compile.md --- uz_UZ/getting-started/compile.md | 64 ++++++++++++++++---------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/uz_UZ/getting-started/compile.md b/uz_UZ/getting-started/compile.md index 046268496..e939dad96 100644 --- a/uz_UZ/getting-started/compile.md +++ b/uz_UZ/getting-started/compile.md @@ -1,82 +1,82 @@ -# Compile +# Tuzish [[toc]] -## Compile command +## Tuzish buyrug‘i -The Goravel project can be compiled with the following command: +Goravel loyihasini quyidagi buyruq orqali tuzish mumkin: ```shell -# Select the system to compile +# Tuzish uchun tizimni tanlash ./artisan build -# Specify the system to compile +# Tuzish uchun tizimni ko‘rsatish ./artisan build --os=linux ./artisan build -o=linux -# Static compilation +# Statik tuzish ./artisan build --static ./artisan build -s -# Specify the output file name +# Chiqish fayli nomini ko‘rsatish ./artisan build --name=goravel ./artisan build -n=goravel ``` -## Manual compilation +## Qo‘lda tuzish -### Regular compilation +### Oddiy tuzish ```shell go build . ``` -#### Deploy Server +#### Serverga joylash -The Following files and folders need to be uploaded to the server during deployment: +Joylash vaqtida serverga quyidagi fayl va papkalarni yuklash kerak: ``` .env -./main // Compile the resulting binary file -./public // if exists -./resources // if exists +./main // Tuzish natijasidagi binar fayl +./public // mavjud bo‘lsa +./resources // mavjud bo‘lsa ``` -### Static compilation +### Statik tuzish -The package by regular compilation also needs to rely on the support of the deployment environment, the statically compiled files can be freely put to run on the specified platform without environment configuration. +Oddiy tuzish orqali olingan paket joylash muhitining qo‘llab-quvvatlashiga muhtoj bo‘ladi, statik tuzilgan fayllarni esa muayyan platformada muhit sozlamasisiz erkin ishlatish mumkin. ```shell go build --ldflags "-extldflags -static" -o main . ``` -### Cross compile +### Platformalararo tuzish -Compilation is differentiated by platform, you need to select a matching compilation method according to the deployment situation. +Tuzish platformaga qarab farqlanadi, joylash holatiga mos tuzish usulini tanlashingiz kerak. ```shell -// Compile Linux environment +// Linux muhiti uchun tuzish CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build . -// Compile Windows environment +// Windows muhiti uchun tuzish CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build . -// Compile Mac environment +// Mac muhiti uchun tuzish CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build . ``` ## Docker -Goravel has a default `Dockerfile` and `docker-compose.yml` file, you can use it directly, note that `APP_HOST` should be `0.0.0.0` at this time. +Goravelning standart `Dockerfile` va `docker-compose.yml` fayli mavjud, ularni to‘g‘ridan-to‘g‘ri ishlatishingiz mumkin, shu paytda `APP_HOST` `0.0.0.0` bo‘lishi kerakligiga e‘tibor bering. ```shell docker build . ``` -If you encounter slow download dependencies and time zone issues, you can optimize the Dockerfile content like the following script: +Agar bog‘liqliklarni yuklash sekin va vaqt mintaqasi muammolari duch kelsangiz, Dockerfile mazmunini quyidagi skript kabi optimallashtirishingiz mumkin: ```dockerfile -# China Special +# Xitoy uchun maxsus FROM golang:alpine AS builder ENV GO111MODULE=on \ @@ -96,7 +96,7 @@ WORKDIR /www COPY --from=builder /build/.env /www/.env COPY --from=builder /build/main /www/ -# If exists +# Mavjud bo‘lsa COPY --from=builder /build/database/ /www/database/ COPY --from=builder /build/public/ /www/public/ COPY --from=builder /build/storage/ /www/storage/ @@ -107,32 +107,32 @@ ENTRYPOINT ["/www/main"] ### Docker Compose -You can also quickly start the service with the following command: +Shuningdek, xizmatni quyidagi buyruq orqali tezda ishga tushirishingiz mumkin: ```shell docker-compose build docker-compose up ``` -> Note: If you need external access, you need to change APP_HOST to 0.0.0.0 +> Eslatma: Agar tashqi kirish kerak bo‘lsa, APP_HOST ni 0.0.0.0 ga o‘zgartirishingiz kerak -## Set timezone +## Vaqt mintaqasini o‘rnatish -When the `app.timezone` configuration is not `UTC`, you need to set the timezone to the application during compilation. You can choose any of the following three methods: +`app.timezone` sozlamasi `UTC` bo‘lmaganda, tuzish vaqtida ilovaga vaqt mintaqasini o‘rnatishingiz kerak. Quyidagi uch usuldan istalgan birini tanlashingiz mumkin: -1. Add timezone settings in Dockerfile +1. Dockerfile faylida vaqt mintaqasi sozlamalarini qo‘shish ``` RUN apk add tzdata && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo "Asia/Shanghai" > /etc/timezone ``` -2. Set timezone during compilation +2. Tuzish vaqtida vaqt mintaqasini o‘rnatish ``` go build -tags timetzdata . ``` -3. Import timezone in `main.go` +3. `main.go` faylida vaqt mintaqasini import qilish ```shell import ( From 3fcef6ffbb86a641ea89783f1c79cf446e792e72 Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 6 Apr 2026 21:53:01 +0800 Subject: [PATCH 115/163] New translations configuration.md (Uzbek) [skip ci] Update translations (Uzbek) configuration.md --- uz_UZ/getting-started/configuration.md | 44 +++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/uz_UZ/getting-started/configuration.md b/uz_UZ/getting-started/configuration.md index 73f65008e..5fd98a218 100644 --- a/uz_UZ/getting-started/configuration.md +++ b/uz_UZ/getting-started/configuration.md @@ -1,24 +1,24 @@ -# Configuration +# Konfiguratsiya [[toc]] -## Introduction +## Kirish -All configuration files of the Goravel framework are stored in the `config` directory. You can view specific instructions and configure them flexibly according to project needs. +Goravel freymvorkining barcha konfiguratsiya fayllari `config` papkasida saqlanadi. Siz aniq ko'rsatmalarni ko'rib chiqishingiz va loyiha ehtiyojlariga mos ravishda ularni moslashuvchan sozlashingiz mumkin. -## Environment Configuration +## Muhit konfiguratsiyasi -Running applications in different environments usually requires different configurations. For example, you may want to turn on the Debug mode locally but don't need it in the production environment. +Ilovalarni turli muhitlarda ishga tushirish odatda turli konfiguratsiyalarni talab qiladi. Misol uchun, siz mahalliy ravishda Debug rejimini yoqishni xohlashingiz mumkin, lekin ishlab chiqarish muhitida bunga ehtiyoj yo'q. -Therefore, the framework provides the `.env.example` file in the root directory. You need to copy this file, rename it to `.env` before you start development, and modify the configuration items in the `.env` file according to your project needs. +Shuning uchun, freymvork ildiz papkasida `.env.example` faylini taqdim etadi. Siz ishlab chiqishni boshlashdan oldin ushbu faylni nusxalashingiz, uni `.env` deb nomini o'zgartirishingiz va `.env` faylidagi konfiguratsiya bandlarini loyiha ehtiyojlariga mos ravishda o'zgartirishingiz kerak. -Note that the `.env` file should not be added to version control, because when multiple people collaborate, different developers may use different configurations, and different deployment environment configurations are different. +Diqqat qiling, `.env` fayli versiyalarni nazorat qilishga qo'shilmasligi kerak, chunki bir nechta odamlar hamkorlik qilganda, turli dasturchilar turli konfiguratsiyalardan foydalanishlari mumkin va turli joylashtirish muhitlari konfiguratsiyalari har xil bo'ladi. -In addition, if an intruder gains access to your code repository, there will be a risk of exposing sensitive configuration. If you want to add a new configuration item, you can add it to the `.env.example` file to synchronize the configuration of all developers. +Bundan tashqari, agar tashqi shaxs sizning kod omboringizga kirish huquqini olgan bo'lsa, sezuvchi konfiguratsiyani oshkor qilish xavfi mavjud bo'ladi. Agar siz yangi konfiguratsiya bandini qo'shmoqchi bo'lsangiz, uni `.env.example` fayliga qo'shishingiz mumkin, shunda barcha dasturchilarning konfiguratsiyasi sinxronlanadi. -### Register Configuration +### Konfiguratsiyani ro'yxatdan o'tkazish -All configuration files will be registered via the `WithConfig` function in the `bootstrap/app.go` file. Given that it's a `init` function in the config file, you don't need to register each configuration file one by one. Just call the `WithConfig` function as follows: +Barcha konfiguratsiya fayllari `bootstrap/app.go` faylidagi `WithConfig` funksiyasi orqali ro'yxatdan o'tkaziladi. Konfiguratsiya faylidagi `init` funksiyasi ekanligini hisobga olgan holda, siz har bir konfiguratsiya faylini birma-bir ro'yxatdan o'tkazishingiz shart emas. Shunchaki `WithConfig` funksiyasini quyidagicha chaqiring: ```go func Boot() contractsfoundation.Application { @@ -28,34 +28,34 @@ func Boot() contractsfoundation.Application { } ``` -## Retrieve Environment Configuration +## Muhit konfiguratsiyasini olish -Use the following method to obtain the configuration items in the `.env` file: +`.env` faylidagi konfiguratsiya bandlarini olish uchun quyidagi usuldan foydalaning: ```go -// The first parameter is the configuration key, and the second parameter is the default value +// Birinchi parametr konfiguratsiya kaliti, ikkinchi parametr standart qiymat facades.Config().Env("APP_NAME", "goravel") ``` -## Access Configuration Values +## Konfiguratsiya qiymatlariga kirish -You can easily use the global `facades.Config()` function anywhere in the application to access the configuration values in the `config` directory. The access to the configuration value can use the "." syntax. You can also specify a default value, if the configuration option does not exist, the default value is returned: +Siz ilovaning istalgan joyidan `config` papkasidagi konfiguratsiya qiymatlariga kirish uchun global `facades.Config()` funksiyasidan osongina foydalanishingiz mumkin. Konfiguratsiya qiymatiga kirish "." sintaksisidan foydalanishi mumkin. Shuningdek, siz standart qiymatni belgilashingiz mumkin, agar konfiguratsiya opsiyasi mavjud bo'lmasa, standart qiymat qaytariladi: ```go -// Get the configuration through assertion +// Tasdiq orqali konfiguratsiyani olish facades.Config().Get("app.name", "goravel") -// Get the configuration of the string type +// String turidagi konfiguratsiyani olish facades.Config().GetString("app.name", "goravel") -// Get the configuration of the int type +// Int turidagi konfiguratsiyani olish facades.Config().GetInt("app.int", 1) -// Get the configuration of the bool type +// Bool turidagi konfiguratsiyani olish facades.Config().GetBool("app.debug", true) ``` -## Set Configuration +## Konfiguratsiyani sozlash ```go facades.Config().Add("path", "value1") @@ -63,9 +63,9 @@ facades.Config().Add("path.with.dot.case1", "value1") facades.Config().Add("path.with.dot", map[string]any{"case3": "value3"}) ``` -## Get Project Information +## Loyiha ma'lumotlarini olish -You can use the `artisan about` command to view the framework version, configuration, etc. +Siz freymvork versiyasi, konfiguratsiyasi va boshqalarni ko'rish uchun `artisan about` buyrug'idan foydalanishingiz mumkin. ```bash ./artisan about From 243c9ece1e3436b43016e95b6ea7b86b395e6a9d Mon Sep 17 00:00:00 2001 From: Wenbo Han Date: Mon, 6 Apr 2026 21:53:02 +0800 Subject: [PATCH 116/163] New translations contributions.md (Uzbek) [skip ci] Update translations (Uzbek) contributions.md --- uz_UZ/prologue/contributions.md | 128 ++++++++++++++++---------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/uz_UZ/prologue/contributions.md b/uz_UZ/prologue/contributions.md index badc9e98f..7995ba4b9 100644 --- a/uz_UZ/prologue/contributions.md +++ b/uz_UZ/prologue/contributions.md @@ -1,19 +1,19 @@ -# Contribution Guide +# Hissa qo‘shish bo‘yicha qo‘llanma [[toc]] -Goravel welcomes rich and diverse contributions from different talents, such as coding, translations, articles, tutorials, etc. After completing two features(5 `Good First Issue` == 1 `Feature`), you will be recognized as a core contributor. By completing one feature every three months, you can maintain this status. +Goravel turli isteʼdodlardan, masalan, kodlash, tarjima, maqola, o‘quv qo‘llanmalari va boshqalardan boy va xilma-xil hissalarni kutib oladi. Ikki xususiyatni (5 ta "Yaxshi birinchi muammo" == 1 ta "Xususiyat") bajarganingizdan so‘ng, siz asosiy hissa qo‘shuvchi sifatida tan olinasiz. Har uch oyda bitta xususiyatni bajarish orqali siz bu maqomni saqlab turishingiz mumkin. -Let's make Goravel more efficient together! +Keling, Goravelni birgalikda yanada samaraliroq qilaylik! -## Reward +## Mukofot -- Core developers will be eligible for benefits when Goravel benefits in the future. -- After completing a `Feature`, you will receive an official Goravel T-Shirt, with a maximum of 1 per major version release cycle. (PS: Because of the difference of country, you may need to help us to find a suitable supplier.) +- Asosiy ishlab chiquvchilar Goravel kelajakda foyda ko‘rganida imtiyozlarga ega bo‘lish huquqiga ega bo‘ladilar. +- "Xususiyat"ni bajarganingizdan so‘ng, siz rasmiy Goravel futbolkasini olasiz, har bir asosiy versiya chiqarish tsikli uchun maksimal 1 ta. (Eslatma: Mamlakat farqi tufayli, siz bizga mos yetkazib beruvchini topishda yordam berishingiz kerak bo‘lishi mumkin.)

-## Core Developers +## Asosiy Ishlab Chiquvchilar
@@ -21,7 +21,7 @@ Let's make Goravel more efficient together!
-## Contributors +## Hissa qo‘shuvchilar
@@ -61,87 +61,87 @@ Let's make Goravel more efficient together!
-## Bug Feedback +## Xato haqida bildirish -You can report Bug Feedback [here](https://github.com/goravel/goravel/issues/new?assignees=&labels=%E2%98%A2%EF%B8%8F+Bug%2Cbug&projects=&template=bug_report.yml&title=%F0%9F%90%9B+%5BBug%5D+), please search [Issue List](https://github.com/goravel/goravel/issues?q=is%3Aissue) for similar questions before submitting. The report should contain a title and a clear description of the problem, as much relevant information as possible, and a code sample that demonstrates the problem. The goal of Bug Feedback is to make it easy for yourself and other persons to reproduce the Bug and develop fixes. Goravel encourages committers to create a PR for the Bug repair at the same time, making the open-source project more actively developed. +Siz Xato haqida bildirishni [bu yerda](https://github.com/goravel/goravel/issues/new?assignees=&labels=%E2%98%A2%EF%B8%8F+Bug%2Cbug&projects=&template=bug_report.yml&title=%F0%9F%90%9B+%5BBug%5D+) topshirishingiz mumkin, iltimos, yuborishdan oldin [Muammolar ro‘yxati](https://github.com/goravel/goravel/issues?q=is%3Aissue) bo‘yicha shunga o‘xshash savollarni qidiring. Hisobot sarlavha va muammoning aniq tavsifini, iloji boricha ko‘proq tegishli ma’lumotni va muammoni namoyish etuvchi kod namunasini o‘z ichiga olishi kerak. Xato haqida bildirishning maqsadi - sizga va boshqalarga xatoni qayta tiklash va tuzatishlar ishlab chiqishni osonlashtirishdir. Goravel ishtirokchilarni xatoni tuzatish uchun bir vaqtning o‘zida PR yaratishga rag‘batlantiradi, bu ochiq manbali loyihani faolroq rivojlantirishga xizmat qiladi. -## Support Questions +## Yordam savollari -Goravel's GitHub issue trackers are not intended to provide Goravel help or support. Instead, use one of the following channels: +Goravelning GitHub muammo kuzatuvchilari Goravel yordami yoki qo‘llab-quvvatlashini ta’minlash uchun mo‘ljallanmagan. Buning o‘rniga quyidagi kanallardan birini ishlating: -- [GitHub Discussions](https://github.com/goravel/goravel/discussions) +- [GitHub Muhokamalari](https://github.com/goravel/goravel/discussions) - [Discord](https://github.com/goravel/goravel/tree/master#group) - [WeChat](https://github.com/goravel/goravel/blob/master/README_zh.md#%E7%BE%A4%E7%BB%84) -## Development Discussion +## Rivojlanish bo‘yicha muhokama -You may propose new features or improvements to existing Goravel behavior in the Goravel framework repository's [GitHub discussion board](https://github.com/goravel/goravel/discussions). Informal discussion regarding bugs, new features, and implementation of existing features takes place in Discord or WeChat. Bowen, the maintainer of Goravel, is typically present in the group on weekdays from 9am-6pm (UTC+08:00), and sporadically present in the group at other times. +Siz Goravel framework omborining [GitHub muhokama doskasida](https://github.com/goravel/goravel/discussions) mavjud Goravel xatti-harakatlari uchun yangi xususiyatlar yoki takomillashtirishlarni taklif qilishingiz mumkin. Xatolar, yangi xususiyatlar va mavjud xususiyatlarni amalga oshirish bo‘yicha norasmiy muhokamalar Discord yoki WeChat-da olib boriladi. Goravelning asoschisi Bowen odatda dushanbadan jumagacha soat 9:00 dan 18:00 gacha (UTC+08:00) guruhda bo‘ladi va boshqa vaqtlarda guruhda tasodifiy bo‘ladi. -## Add A New Language +## Yangi Til Qo‘shish -Welcome to add a new language to the Goravel documentation, you can submit an issue with the title `Add [Language] Language` and your [Crowdin](https://crowdin.com/) account to [goravel/goravel](https://github.com/goravel/goravel/issues/new). We will invite you to the Crowdin project. +Goravel hujjatlariga yangi til qo‘shishga xush kelibsiz, siz `[Til] Tilini Qo‘shish` sarlavhasi va [Crowdin](https://crowdin.com/) hisobingiz bilan muammoni [goravel/goravel](https://github.com/goravel/goravel/issues/new) ga yuborishingiz mumkin. Biz sizni Crowdin loyihasiga taklif qilamiz. -## Modify Existing Languages +## Mavjud Tillarni O‘zgartirish -Given that the Goravel documentation supports i18n, only the English language can be modified by PR; other languages should be modified via [Crowdin](https://crowdin.com/). You can submit an issue with the title `Modify [Language] Language` and your [Crowdin](https://crowdin.com/) account to [goravel/goravel](https://github.com/goravel/goravel/issues/new). We will invite you to the Crowdin project. +Goravel hujjatlari i18n-ni qo‘llab-quvvatlaydi, faqat ingliz tilini PR orqali o‘zgartirish mumkin; boshqa tillar [Crowdin](https://crowdin.com/) orqali o‘zgartirilishi kerak. Siz `[Til] Tilini O‘zgartirish` sarlavhasi va [Crowdin](https://crowdin.com/) hisobingiz bilan muammoni [goravel/goravel](https://github.com/goravel/goravel/issues/new) ga yuborishingiz mumkin. Biz sizni Crowdin loyihasiga taklif qilamiz. -## Contribution +## Hissa qo‘shish -### Find/Create Issue +### Muammo Topish/Yaratish -You can find or create an issue in [Issue List](https://github.com/goravel/goravel/issues), leave a message to express your willingness to deal with the issue, once confirmed by the repository maintainer, the process can be started. +Siz [Muammolar ro‘yxati](https://github.com/goravel/goravel/issues) da muammo topishingiz yoki yaratishingiz mumkin, muammoni hal qilish istagingizni bildirish uchun xabar qoldiring, ombor asoschisi tomonidan tasdiqlangandan so‘ng, jarayonni boshlash mumkin. -### Create PR +### PR Yaratish -- You can check out [this article](https://docs.github.com/en/get-started/quickstart/contributing-to-projects) if you are new to the process; -- During the development process, if you encounter a problem, you can describe the problem in detail in issue at any time for future communication, but before that, please make sure that you have tried to solve the problem through Google and other methods as much as possible; -- Before creating a PR, please improve the unit test coverage as much as possible to provide more stable functions; -- If you modify any file under the `contracts` folder, please run the `go tool mockery` command in the root directory to generate the mock file; -- When the PR is developed, please add the `Review Ready `, the maintainer will review it in a timely manner. -- After the PR is merged, the issue will be closed automatically if the description in the PR is set correctly; -- Goravel greatly appreciates your contribution and will add you to the home contribution list at the next release; ❤️ +- Agar siz bu jarayonda yangi bo‘lsangiz, [ushbu maqolani](https://docs.github.com/en/get-started/quickstart/contributing-to-projects) tekshirishingiz mumkin; +- Rivojlanish jarayonida, agar siz muammoga duch kelsangiz, kelajakdagi muloqot uchun har qanday vaqtda muammoni batafsil tasvirlashingiz mumkin, ammo bundan oldin, muammoni Google va boshqa usullar orqali iloji boricha hal qilishga harakat qilganingizga ishonch hosil qiling; +- PR yaratishdan oldin, iloji boricha birlik test qamrovini yaxshilang, barqarorroq funktsiyalarni ta’minlash uchun; +- Agar siz `contracts` papkasidagi har qanday faylni oʻzgartirsangiz, mock faylini yaratish uchun ildiz katalogida `go tool mockery` buyrugʻini ishga tushiring; +- PR ishlab chiqilganda, iltimos, "Ko‘rib chiqishga tayyor" yorlig‘ini qo‘shing, asoschi uni o‘z vaqtida ko‘rib chiqadi. +- PR birlashtirilgandan so‘ng, agar PR dagi tavsif to‘g‘ri o‘rnatilgan bo‘lsa, muammo avtomatik ravishda yopiladi; +- Goravel sizning hissangizni juda qadrlaydi va sizni keyingi relizda asosiy hissa qo‘shuvchilar ro‘yxatiga qo‘shadi; ❤️ -## Which Branch? +## Qaysi Tarmoq? -**All** bug fixes should be sent to the latest version that supports bug fixes, unless they fix features that exist only in the upcoming release. +**Barcha** xato tuzatishlari xatolarni tuzatishni qo‘llab-quvvatlaydigan eng so‘nggi versiyaga yuborilishi kerak, agar ular faqat kelgusi relizda mavjud bo‘lgan xususiyatlarni tuzatmasa. -**New features** or features with breaking changes should always be sent to the `master` branch. +**Yangi xususiyatlar** yoki buzilishli o‘zgarishlarga ega bo‘lgan xususiyatlar har doim "master" tarmog‘iga yuborilishi kerak. -## Goravel Repository +## Goravel Ombori -| Repository | Action | -| --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [goravel/goravel](https://github.com/goravel/goravel) | Goravel artisans | -| [goravel/goravel-lite](https://github.com/goravel/goravel-lite) | Goravel artisans of lite | -| [goravel/framework](https://github.com/goravel/framework) | Goravel main repository | -| [goravel/example](https://github.com/goravel/example) | Goravel example | -| [goravel/example-proto](https://github.com/goravel/example-proto) | The proto dependency of example | -| [goravel/example-package](https://github.com/goravel/example-package) | Example for package | -| [goravel/installer](https://github.com/goravel/installer) | A command-line tool that helps you to install the Goravel framework | -| [goravel/release](https://github.com/goravel/release) | Prover a simple way to release framework and packages version | -| [goravel/docs](https://github.com/goravel/docs) | Document | -| [goravel/s3](https://github.com/goravel/s3) | The S3 driver of Storage module | -| [goravel/oss](https://github.com/goravel/oss) | The OSS driver of Storage module | -| [goravel/cos](https://github.com/goravel/cos) | The COS driver of Storage module | -| [goravel/minio](https://github.com/goravel/minio) | The Minio driver of Storage module | -| [goravel/redis](https://github.com/goravel/redis) | The Redis driver of Cache module | -| [goravel/gin](https://github.com/goravel/gin) | The Gin driver of Route module | -| [goravel/fiber](https://github.com/goravel/fiber) | The Fiber driver of Route module | -| [goravel/postgres](https://github.com/goravel/postgres) | The Postgres driver of Database module | -| [goravel/mysql](https://github.com/goravel/mysql) | The MySQL driver of Database module | -| [goravel/sqlserver](https://github.com/goravel/sqlserver) | The SQLServer driver of Database module | -| [goravel/sqlite](https://github.com/goravel/sqlite) | The SQLite driver of Database module | -| [goravel/file-rotatelogs](https://github.com/goravel/file-rotatelogs) | Providers log splitting functionality for Log module | -| [goravel/.github](https://github.com/goravel/.github) | [Community health file](https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/creating-a-default-community-health-file) | +| Ombor | Harakat | +| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| [goravel/goravel](https://github.com/goravel/goravel) | Goravel ustalari | +| [goravel/goravel-lite](https://github.com/goravel/goravel-lite) | Goravelning lite ustalari | +| [goravel/framework](https://github.com/goravel/framework) | Goravel asosiy ombori | +| [goravel/example](https://github.com/goravel/example) | Goravel namuna | +| [goravel/example-proto](https://github.com/goravel/example-proto) | Namunaning proto bog‘liqligi | +| [goravel/example-package](https://github.com/goravel/example-package) | Paket uchun namuna | +| [goravel/installer](https://github.com/goravel/installer) | Goravel frameworkini oʻrnatishda yordam beradigan buyruq qatori vositasi | +| [goravel/release](https://github.com/goravel/release) | Framework va paketlar versiyasini chiqarishning oddiy usulini taqdim etadi | +| [goravel/docs](https://github.com/goravel/docs) | Hujjat | +| [goravel/s3](https://github.com/goravel/s3) | Saqlash modulining S3 drayveri | +| [goravel/oss](https://github.com/goravel/oss) | Saqlash modulining OSS drayveri | +| [goravel/cos](https://github.com/goravel/cos) | Saqlash modulining COS drayveri | +| [goravel/minio](https://github.com/goravel/minio) | Saqlash modulining Minio drayveri | +| [goravel/redis](https://github.com/goravel/redis) | Kesh modulining Redis drayveri | +| [goravel/gin](https://github.com/goravel/gin) | Marshrut modulining Gin drayveri | +| [goravel/fiber](https://github.com/goravel/fiber) | Route modulining Fiber drayveri | +| [goravel/postgres](https://github.com/goravel/postgres) | Database modulining Postgres drayveri | +| [goravel/mysql](https://github.com/goravel/mysql) | Database modulining MySQL drayveri | +| [goravel/sqlserver](https://github.com/goravel/sqlserver) | Database modulining SQLServer drayveri | +| [goravel/sqlite](https://github.com/goravel/sqlite) | Database modulining SQLite drayveri | +| [goravel/file-rotatelogs](https://github.com/goravel/file-rotatelogs) | Log moduli uchun jurnalni boʻlish funksionalligini taqdim etadi | +| [goravel/.github](https://github.com/goravel/.github) | [Jamiyat sogʻligʻi fayli](https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/creating-a-default-community-health-file) | -## Code of Conduct +## Xulq qoidalari -The Goravel code of conduct is derived from the Laravel code of conduct. Any violations of the code of conduct may be reported to Bowen. +Goravelning xulq qoidalari Laravelning xulq qoidalaridan olingan. Xulq qoidalarining har qanday buzilishi Bowen'ga xabar berilishi mumkin. -- Participants will be tolerant of opposing views. -- Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks. -- When interpreting the words and actions of others, participants should always assume good intentions. -- Behavior that can be reasonably considered harassment will not be tolerated. +- Ishtirokchilar qarama-qarshi qarashlarga bagʻrikeng boʻlishadi. +- Ishtirokchilar oʻzlarining til va harakatlari shaxsiy hujumlar va shaxsiy haqoratlardan xoli ekanligiga ishonch hosil qilishlari kerak. +- Boshqalarning soʻz va harakatlarini talqin qilishda, ishtirokchilar har doim yaxshi niyat bor deb hisoblashlari kerak. +- Oqilona ravishda bezovtalik deb hisoblanishi mumkin boʻlgan xatti-harakatlarga yoʻl qoʻyilmaydi.