diff --git a/original-en/authorization.md b/original-en/authorization.md index 07227cd..52d30ff 100644 --- a/original-en/authorization.md +++ b/original-en/authorization.md @@ -245,7 +245,7 @@ Similar to the `before` method, if the `after` closure returns a non-null result ### Inline Authorization -Occasionally, you may wish to determine if the currently authenticated user is authorized to perform a given action without writing a dedicated gate that corresponds to the action. Laravel allows you to perform these types of "inline" authorization checks via the `Gate::allowIf` and `Gate::denyIf` methods: +Occasionally, you may wish to determine if the currently authenticated user is authorized to perform a given action without writing a dedicated gate that corresponds to the action. Laravel allows you to perform these types of "inline" authorization checks via the `Gate::allowIf` and `Gate::denyIf` methods. Inline authorization does not execute any defined ["before" or "after" authorization hooks](#intercepting-gate-checks): ```php use App\Models\User; diff --git a/original-en/cashier-paddle.md b/original-en/cashier-paddle.md index 839096d..a903d93 100644 --- a/original-en/cashier-paddle.md +++ b/original-en/cashier-paddle.md @@ -10,6 +10,9 @@ - [Paddle JS](#paddle-js) - [Currency Configuration](#currency-configuration) - [Overriding Default Models](#overriding-default-models) +- [Quickstart](#quickstart) + - [Selling Products](#quickstart-selling-products) + - [Selling Subscriptions](#quickstart-selling-subscriptions) - [Checkout Sessions](#checkout-sessions) - [Overlay Checkout](#overlay-checkout) - [Inline Checkout](#inline-checkout) @@ -192,17 +195,234 @@ After defining your model, you may instruct Cashier to use your custom model via Cashier::useTransactionModel(Transaction::class); } + +## Quickstart + + +### Selling Products + +> [!NOTE] +> Before utilizing Paddle Checkout, you should define Products with fixed prices in your Paddle dashboard. In addition, you should [configure Paddle's webhook handling](#handling-paddle-webhooks). + +Offering product and subscription billing via your application can be intimidating. However, thanks to Cashier and [Paddle's Checkout Overlay](https://www.paddle.com/billing/checkout), you can easily build modern, robust payment integrations. + +To charge customers for non-recurring, single-charge products, we'll utilize Cashier to charge customers with Paddle's Checkout Overlay, where they will provide their payment details and confirm their purchase. Once the payment has been made via the Checkout Overlay, the customer will be redirected to a success URL of your choosing within your application: + + use Illuminate\Http\Request; + + Route::get('/buy', function (Request $request) { + $checkout = $request->user()->checkout('pri_deluxe_album') + ->returnTo(route('dashboard')); + + return view('buy', ['checkout' => $checkout]); + })->name('checkout'); + +As you can see in the example above, we will utilize Cashier's provided `checkout` method to create a checkout object to present the customer the Paddle Checkout Overlay for a given "price identifier". When using Paddle, "prices" refer to [defined prices for specific products](https://developer.paddle.com/build/products/create-products-prices). + +If necessary, the `checkout` method will automatically create a customer in Paddle and connect that Paddle customer record to the corresponding user in your application's database. After completing the checkout session, the customer will be redirected to a dedicated success page where you can display an informational message to the customer. + +In the `buy` view, we will include a button to display the Checkout Overlay. The `paddle-button` Blade component is included with Cashier Paddle; however, you may also [manually render an overlay checkout](#manually-rendering-an-overlay-checkout): + +```html + + Buy Product + +``` + + +#### Providing Meta Data to Paddle Checkout + +When selling products, it's common to keep track of completed orders and purchased products via `Cart` and `Order` models defined by your own application. When redirecting customers to Paddle's Checkout Overlay to complete a purchase, you may need to provide an existing order identifier so that you can associate the completed purchase with the corresponding order when the customer is redirected back to your application. + +To accomplish this, you may provide an array of custom data to the `checkout` method. Let's imagine that a pending `Order` is created within our application when a user begins the checkout process. Remember, the `Cart` and `Order` models in this example are illustrative and not provided by Cashier. You are free to implement these concepts based on the needs of your own application: + + use App\Models\Cart; + use App\Models\Order; + use Illuminate\Http\Request; + + Route::get('/cart/{cart}/checkout', function (Request $request, Cart $cart) { + $order = Order::create([ + 'cart_id' => $cart->id, + 'price_ids' => $cart->price_ids, + 'status' => 'incomplete', + ]); + + $checkout = $request->user()->checkout($order->price_ids) + ->customData(['order_id' => $order->id]); + + return view('billing', ['checkout' => $checkout]); + })->name('checkout'); + +As you can see in the example above, when a user begins the checkout process, we will provide all of the cart / order's associated Paddle price identifiers to the `checkout` method. Of course, your application is responsible for associating these items with the "shopping cart" or order as a customer adds them. We also provide the order's ID to the Paddle Checkout Overlay via the `customData` method. + +Of course, you will likely want to mark the order as "complete" once the customer has finished the checkout process. To accomplish this, you may listen to the webhooks dispatched by Paddle and raised via events by Cashier to store order information in your database. + +To get started, listen for the `TransactionCompleted` event dispatched by Cashier. Typically, you should register the event listener in the `boot` method of one of your application's service providers: + + use App\Listeners\CompleteOrder; + use Illuminate\Support\Facades\Event; + use Laravel\Paddle\Events\TransactionCompleted; + + /** + * Bootstrap any application services. + */ + public function boot(): void + { + Event::listen(TransactionCompleted::class, CompleteOrder::class); + } + +In this example, the `CompleteOrder` listener might look like the following: + + namespace App\Listeners; + + use App\Models\Order; + use Laravel\Cashier\Cashier; + use Laravel\Cashier\Events\TransactionCompleted; + + class CompleteOrder + { + /** + * Handle the incoming Cashier webhook event. + */ + public function handle(TransactionCompleted $event): void + { + $orderId = $event->payload['data']['custom_data']['order_id'] ?? null; + + $order = Order::findOrFail($orderId); + + $order->update(['status' => 'completed']); + } + } + +Please refer to Paddle's documentation for more information on the [data contained by the `transaction.completed` event](https://developer.paddle.com/webhooks/transactions/transaction-completed). + + +### Selling Subscriptions + +> [!NOTE] +> Before utilizing Paddle Checkout, you should define Products with fixed prices in your Paddle dashboard. In addition, you should [configure Paddle's webhook handling](#handling-paddle-webhooks). + +Offering product and subscription billing via your application can be intimidating. However, thanks to Cashier and [Paddle's Checkout Overlay](https://www.paddle.com/billing/checkout), you can easily build modern, robust payment integrations. + +To learn how to sell subscriptions using Cashier and Paddle's Checkout Overlay, let's consider the simple scenario of a subscription service with a basic monthly (`price_basic_monthly`) and yearly (`price_basic_yearly`) plan. These two prices could be grouped under a "Basic" product (`pro_basic`) in our Paddle dashboard. In addition, our subscription service might offer an Expert plan as `pro_expert`. + +First, let's discover how a customer can subscribe to our services. Of course, you can imagine the customer might click a "subscribe" button for the Basic plan on our application's pricing page. This button will invoke a Paddle Checkout Overlay for their chosen plan. To get started, let's initiate a checkout session via the `checkout` method: + + use Illuminate\Http\Request; + + Route::get('/subscribe', function (Request $request) { + $checkout = $request->user()->checkout('price_basic_monthly') + ->returnTo(route('dashboard')); + + return view('subscribe', ['checkout' => $checkout]); + })->name('subscribe'); + +In the `subscribe` view, we will include a button to display the Checkout Overlay. The `paddle-button` Blade component is included with Cashier Paddle; however, you may also [manually render an overlay checkout](#manually-rendering-an-overlay-checkout): + +```html + + Subscribe + +``` + +Now, when the Subscribe button is clicked, the customer will be able to enter their payment details and initiate their subscription. To know when their subscription has actually started (since some payment methods require a few seconds to process), you should also [configure Cashier's webhook handling](#handling-paddle-webhooks). + +Now that customers can start subscriptions, we need to restrict certain portions of our application so that only subscribed users can access them. Of course, we can always determine a user's current subscription status via the `subscribed` method provided by Cashier's `Billable` trait: + +```blade +@if ($user->subscribed()) +

You are subscribed.

+@endif +``` + +We can even easily determine if a user is subscribed to specific product or price: + +```blade +@if ($user->subscribedToProduct('pro_basic')) +

You are subscribed to our Basic product.

+@endif + +@if ($user->subscribedToPrice('price_basic_monthly')) +

You are subscribed to our monthly Basic plan.

+@endif +``` + + +#### Building a Subscribed Middleware + +For convenience, you may wish to create a [middleware](/docs/{{version}}/middleware) which determines if the incoming request is from a subscribed user. Once this middleware has been defined, you may easily assign it to a route to prevent users that are not subscribed from accessing the route: + + user()?->subscribed()) { + // Redirect user to billing page and ask them to subscribe... + return redirect('/subscribe'); + } + + return $next($request); + } + } + +Once the middleware has been defined, you may assign it to a route: + + use App\Http\Middleware\Subscribed; + + Route::get('/dashboard', function () { + // ... + })->middleware([Subscribed::class]); + + +#### Allowing Customers to Manage Their Billing Plan + +Of course, customers may want to change their subscription plan to another product or "tier". In our example from above, we'd want to allow the customer to change their plan from a monthly subscription to a yearly subscription. For this you'll need to implement something like a button that leads to the below route: + + use Illuminate\Http\Request; + + Route::put('/subscription/{price}/swap', function (Request $request, $price) { + $user->subscription()->swap($price); // With "$price" being "price_basic_yearly" for this example. + + return redirect()->route('dashboard'); + })->name('subscription.swap'); + +Besides swapping plans you'll also need to allow your customers to cancel their subscription. Like swapping plans, provide a button that leads to the following route: + + use Illuminate\Http\Request; + + Route::put('/subscription/cancel', function (Request $request, $price) { + $user->subscription()->cancel(); + + return redirect()->route('dashboard'); + })->name('subscription.cancel'); + +And now your subscription will get cancelled at the end of its billing period. + +> [!NOTE] +> As long as you have configured Cashier's webhook handling, Cashier will automatically keep your application's Cashier-related database tables in sync by inspecting the incoming webhooks from Paddle. So, for example, when you cancel a customer's subscription via Paddle's dashboard, Cashier will receive the corresponding webhook and mark the subscription as "cancelled" in your application's database. + ## Checkout Sessions -Most operations to bill customers are performed using "checkouts" via Paddle's [checkout overlay widget](https://developer.paddle.com/build/checkout/build-overlay-checkout) or by utilizing [inline checkout](https://developer.paddle.com/build/checkout/build-branded-inline-checkout). +Most operations to bill customers are performed using "checkouts" via Paddle's [Checkout Overlay widget](https://developer.paddle.com/build/checkout/build-overlay-checkout) or by utilizing [inline checkout](https://developer.paddle.com/build/checkout/build-branded-inline-checkout). Before processing checkout payments using Paddle, you should define your application's [default payment link](https://developer.paddle.com/build/transactions/default-payment-link#set-default-link) in your Paddle checkout settings dashboard. ### Overlay Checkout -Before displaying the checkout overlay widget, you must generate a checkout session using Cashier. A checkout session will inform the checkout widget of the billing operation that should be performed: +Before displaying the Checkout Overlay widget, you must generate a checkout session using Cashier. A checkout session will inform the checkout widget of the billing operation that should be performed: use Illuminate\Http\Request; diff --git a/original-en/homestead.md b/original-en/homestead.md index e27086e..b61bfb3 100644 --- a/original-en/homestead.md +++ b/original-en/homestead.md @@ -20,7 +20,7 @@ - [Connecting to Databases](#connecting-to-databases) - [Database Backups](#database-backups) - [Configuring Cron Schedules](#configuring-cron-schedules) - - [Configuring MailHog](#configuring-mailhog) + - [Configuring Mailpit](#configuring-mailpit) - [Configuring Minio](#configuring-minio) - [Laravel Dusk](#laravel-dusk) - [Sharing Your Environment](#sharing-your-environment) @@ -36,7 +36,7 @@ ## Introduction -Laravel strives to make the entire PHP development experience delightful, including your local development environment. [Laravel Homestead](https://github.com/laravel/homestead) is an official, pre-packaged Vagrant box that provides you a wonderful development environment without requiring you to install PHP, a web server, and any other server software on your local machine. +Laravel strives to make the entire PHP development experience delightful, including your local development environment. [Laravel Homestead](https://github.com/laravel/homestead) is an official, pre-packaged Vagrant box that provides you a wonderful development environment without requiring you to install PHP, a web server, or any other server software on your local machine. [Vagrant](https://www.vagrantup.com) provides a simple, elegant way to manage and provision Virtual Machines. Vagrant boxes are completely disposable. If something goes wrong, you can destroy and re-create the box in minutes! @@ -58,8 +58,9 @@ Homestead runs on any Windows, macOS, or Linux system and includes Nginx, PHP, M
-- Ubuntu 20.04 +- Ubuntu 22.04 - Git +- PHP 8.3 - PHP 8.2 - PHP 8.1 - PHP 8.0 @@ -80,7 +81,7 @@ Homestead runs on any Windows, macOS, or Linux system and includes Nginx, PHP, M - Redis - Memcached - Beanstalkd -- Mailhog +- Mailpit - avahi - ngrok - Xdebug @@ -116,7 +117,6 @@ Homestead runs on any Windows, macOS, or Linux system and includes Nginx, PHP, M - Grafana - InfluxDB - Logstash -- Mailpit (Replaces Mailhog) - MariaDB - Meilisearch - MinIO @@ -346,12 +346,10 @@ features: - grafana: true - influxdb: true - logstash: true - - mailpit: true - mariadb: true - meilisearch: true - minio: true - mongodb: true - - mysql: true - neo4j: true - ohmyzsh: true - openresty: true @@ -558,7 +556,7 @@ Below is a list of additional Homestead service ports that you may wish to map f - **MySQL:** 33060 → To 3306 - **PostgreSQL:** 54320 → To 5432 - **MongoDB:** 27017 → To 27017 -- **Mailhog:** 8025 → To 8025 +- **Mailpit:** 8025 → To 8025 - **Minio:** 9600 → To 9600
@@ -566,7 +564,7 @@ Below is a list of additional Homestead service ports that you may wish to map f ### PHP Versions -Homestead supports running multiple versions of PHP on the same virtual machine. You may specify which version of PHP to use for a given site within your `Homestead.yaml` file. The available PHP versions are: "5.6", "7.0", "7.1", "7.2", "7.3", "7.4", "8.0", "8.1", and "8.2" (the default): +Homestead supports running multiple versions of PHP on the same virtual machine. You may specify which version of PHP to use for a given site within your `Homestead.yaml` file. The available PHP versions are: "5.6", "7.0", "7.1", "7.2", "7.3", "7.4", "8.0", "8.1", "8.2", and "8.3", (the default): ```yaml sites: @@ -587,6 +585,7 @@ php7.4 artisan list php8.0 artisan list php8.1 artisan list php8.2 artisan list +php8.3 artisan list ``` You may change the default version of PHP used by the CLI by issuing the following commands from within your Homestead virtual machine: @@ -601,6 +600,7 @@ php74 php80 php81 php82 +php83 ``` @@ -636,10 +636,10 @@ sites: The cron job for the site will be defined in the `/etc/cron.d` directory of the Homestead virtual machine. - -### Configuring MailHog + +### Configuring Mailpit -[MailHog](https://github.com/mailhog/MailHog) allows you to intercept your outgoing email and examine it without actually sending the mail to its recipients. To get started, update your application's `.env` file to use the following mail settings: +[Mailpit](https://github.com/axllent/mailpit) allows you to intercept your outgoing email and examine it without actually sending the mail to its recipients. To get started, update your application's `.env` file to use the following mail settings: ```ini MAIL_MAILER=smtp @@ -650,7 +650,7 @@ MAIL_PASSWORD=null MAIL_ENCRYPTION=null ``` -Once MailHog has been configured, you may access the MailHog dashboard at `http://localhost:8025`. +Once Mailpit has been configured, you may access the Mailpit dashboard at `http://localhost:8025`. ### Configuring Minio diff --git a/original-en/scout.md b/original-en/scout.md index 79a0ed1..946d403 100644 --- a/original-en/scout.md +++ b/original-en/scout.md @@ -2,8 +2,11 @@ - [Introduction](#introduction) - [Installation](#installation) - - [Driver Prerequisites](#driver-prerequisites) - [Queueing](#queueing) +- [Driver Prerequisites](#driver-prerequisites) + - [Algolia](#algolia) + - [Meilisearch](#meilisearch) + - [Typesense](#typesense) - [Configuration](#configuration) - [Configuring Model Indexes](#configuring-model-indexes) - [Configuring Searchable Data](#configuring-searchable-data) @@ -32,7 +35,7 @@ [Laravel Scout](https://github.com/laravel/scout) provides a simple, driver based solution for adding full-text search to your [Eloquent models](/docs/{{version}}/eloquent). Using model observers, Scout will automatically keep your search indexes in sync with your Eloquent records. -Currently, Scout ships with [Algolia](https://www.algolia.com/), [Meilisearch](https://www.meilisearch.com), and MySQL / PostgreSQL (`database`) drivers. In addition, Scout includes a "collection" driver that is designed for local development usage and does not require any external dependencies or third-party services. Furthermore, writing custom drivers is simple and you are free to extend Scout with your own search implementations. +Currently, Scout ships with [Algolia](https://www.algolia.com/), [Meilisearch](https://www.meilisearch.com), [Typesense](https://typesense.org), and MySQL / PostgreSQL (`database`) drivers. In addition, Scout includes a "collection" driver that is designed for local development usage and does not require any external dependencies or third-party services. Furthermore, writing custom drivers is simple and you are free to extend Scout with your own search implementations. ## Installation @@ -63,11 +66,33 @@ Finally, add the `Laravel\Scout\Searchable` trait to the model you would like to use Searchable; } + +### Queueing + +While not strictly required to use Scout, you should strongly consider configuring a [queue driver](/docs/{{version}}/queues) before using the library. Running a queue worker will allow Scout to queue all operations that sync your model information to your search indexes, providing much better response times for your application's web interface. + +Once you have configured a queue driver, set the value of the `queue` option in your `config/scout.php` configuration file to `true`: + + 'queue' => true, + +Even when the `queue` option is set to `false`, it's important to remember that some Scout drivers like Algolia and Meilisearch always index records asynchronously. Meaning, even though the index operation has completed within your Laravel application, the search engine itself may not reflect the new and updated records immediately. + +To specify the connection and queue that your Scout jobs utilize, you may define the `queue` configuration option as an array: + + 'queue' => [ + 'connection' => 'redis', + 'queue' => 'scout' + ], + +Of course, if you customize the connection and queue that Scout jobs utilize, you should run a queue worker to process jobs on that connection and queue: + + php artisan queue:work redis --queue=scout + -### Driver Prerequisites +## Driver Prerequisites -#### Algolia +### Algolia When using the Algolia driver, you should configure your Algolia `id` and `secret` credentials in your `config/scout.php` configuration file. Once your credentials have been configured, you will also need to install the Algolia PHP SDK via the Composer package manager: @@ -76,7 +101,7 @@ composer require algolia/algoliasearch-client-php ``` -#### Meilisearch +### Meilisearch [Meilisearch](https://www.meilisearch.com) is a blazingly fast and open source search engine. If you aren't sure how to install Meilisearch on your local machine, you may use [Laravel Sail](/docs/{{version}}/sail#meilisearch), Laravel's officially supported Docker development environment. @@ -101,27 +126,86 @@ In addition, you should ensure that you install a version of `meilisearch/meilis > [!WARNING] > When upgrading Scout on an application that utilizes Meilisearch, you should always [review any additional breaking changes](https://github.com/meilisearch/Meilisearch/releases) to the Meilisearch service itself. - -### Queueing + +### Typesense -While not strictly required to use Scout, you should strongly consider configuring a [queue driver](/docs/{{version}}/queues) before using the library. Running a queue worker will allow Scout to queue all operations that sync your model information to your search indexes, providing much better response times for your application's web interface. +[Typesense](https://typesense.org) is a lightning-fast, open source search engine and supports keyword search, semantic search, geo search, and vector search. -Once you have configured a queue driver, set the value of the `queue` option in your `config/scout.php` configuration file to `true`: +You can [self-host](https://typesense.org/docs/guide/install-typesense.html#option-2-local-machine-self-hosting) Typesense or use [Typesense Cloud](https://cloud.typesense.org). - 'queue' => true, +To get started using Typesense with Scout, install the Typesense PHP SDK via the Composer package manager: -Even when the `queue` option is set to `false`, it's important to remember that some Scout drivers like Algolia and Meilisearch always index records asynchronously. Meaning, even though the index operation has completed within your Laravel application, the search engine itself may not reflect the new and updated records immediately. +```shell +composer require typesense/typesense-php +``` -To specify the connection and queue that your Scout jobs utilize, you may define the `queue` configuration option as an array: +Then, set the `SCOUT_DRIVER` environment variable as well as your Typesense host and API key credentials within your application's .env file: - 'queue' => [ - 'connection' => 'redis', - 'queue' => 'scout' +```env +SCOUT_DRIVER=typesense +TYPESENSE_API_KEY=masterKey +TYPESENSE_HOST=localhost +``` + +If needed, you may also specify your installation's port, path, and protocol: + +```env +TYPESENSE_PORT=8108 +TYPESENSE_PATH= +TYPESENSE_PROTOCOL=http +``` + +Additional settings and schema definitions for your Typesense collections can be found within your application's `config/scout.php` configuration file. For more information regarding Typesense, please consult the [Typesense documentation](https://typesense.org/docs/guide/#quick-start). + + +#### Preparing Data for Storage in Typesense + +When utilizing Typesense, your searchable model's must define a `toSearchableArray` method that casts your model's primary key to a string and creation date to a UNIX timestamp: + +```php +/** + * Get the indexable data array for the model. + * + * @return array + */ +public function toSearchableArray() +{ + return array_merge($this->toArray(),[ + 'id' => (string) $this->id, + 'created_at' => $this->created_at->timestamp, + ]); +} +``` + +If your searchable model is soft deletable, you should define a `__soft_deleted` field in the model's corresponding Typesense schema within your application's `config/scout.php` configuration file: + +```php +User::class => [ + 'collection-schema' => [ + 'fields' => [ + // ... + [ + 'name' => '__soft_deleted', + 'type' => 'int32', + 'optional' => true, + ], + ], ], +], +``` -Of course, if you customize the connection and queue that Scout jobs utilize, you should run a queue worker to process jobs on that connection and queue: + +#### Dynamic Search Parameters - php artisan queue:work redis --queue=scout +Typesense allows you to modify your [search parameters](https://typesense.org/docs/latest/api/search.html#search-parameters) dynamically when performing a search operation via the `withSearchParameters` method: + +```php +use App\Models\Todo; + +Todo::search('Groceries')->withSearchParameters([ + 'query_by' => 'title, description' +])->get(); +``` ## Configuration @@ -323,7 +407,7 @@ To use the database engine, you may simply set the value of the `SCOUT_DRIVER` e SCOUT_DRIVER=database ``` -Once you have specified the database engine as your preferred driver, you must [configure your searchable data](#configuring-searchable-data). Then, you may start [executing search queries](#searching) against your models. Search engine indexing, such as the indexing needed to seed Algolia or Meilisearch indexes, is unnecessary when using the database engine. +Once you have specified the database engine as your preferred driver, you must [configure your searchable data](#configuring-searchable-data). Then, you may start [executing search queries](#searching) against your models. Search engine indexing, such as the indexing needed to seed Algolia, Meilisearch or Typesense indexes, is unnecessary when using the database engine. #### Customizing Database Searching Strategies @@ -359,7 +443,7 @@ public function toSearchableArray(): array ### Collection Engine -While you are free to use the Algolia or Meilisearch search engines during local development, you may find it more convenient to get started with the "collection" engine. The collection engine will use "where" clauses and collection filtering on results from your existing database to determine the applicable search results for your query. When using this engine, it is not necessary to "index" your searchable models, as they will simply be retrieved from your local database. +While you are free to use the Algolia, Meilisearch, or Typesense search engines during local development, you may find it more convenient to get started with the "collection" engine. The collection engine will use "where" clauses and collection filtering on results from your existing database to determine the applicable search results for your query. When using this engine, it is not necessary to "index" your searchable models, as they will simply be retrieved from your local database. To use the collection engine, you may simply set the value of the `SCOUT_DRIVER` environment variable to `collection`, or specify the `collection` driver directly in your application's `scout` configuration file: @@ -367,7 +451,7 @@ To use the collection engine, you may simply set the value of the `SCOUT_DRIVER` SCOUT_DRIVER=collection ``` -Once you have specified the collection driver as your preferred driver, you may start [executing search queries](#searching) against your models. Search engine indexing, such as the indexing needed to seed Algolia or Meilisearch indexes, is unnecessary when using the collection engine. +Once you have specified the collection driver as your preferred driver, you may start [executing search queries](#searching) against your models. Search engine indexing, such as the indexing needed to seed Algolia, Meilisearch, or Typesense indexes, is unnecessary when using the collection engine. #### Differences From Database Engine diff --git a/original-en/testing.md b/original-en/testing.md index d38515d..69ac8ac 100644 --- a/original-en/testing.md +++ b/original-en/testing.md @@ -81,7 +81,7 @@ Once the test has been generated, you may define test methods as you normally wo } > [!WARNING] -> If you define your own `setUp` / `tearDown` methods within a test class, be sure to call the respective `parent::setUp()` / `parent::tearDown()` methods on the parent class. +> If you define your own `setUp` / `tearDown` methods within a test class, be sure to call the respective `parent::setUp()` / `parent::tearDown()` methods on the parent class. Typically, you should invoke `parent::setUp()` at the start of your own `setUp` method, and `parent::tearDown()` at the end of your `tearDown` method. ## Running Tests diff --git a/original-en/validation.md b/original-en/validation.md index 6f30955..19f4f19 100644 --- a/original-en/validation.md +++ b/original-en/validation.md @@ -934,7 +934,6 @@ Below is a list of all available validation rules and their function: [Not Regex](#rule-not-regex) [Nullable](#rule-nullable) [Numeric](#rule-numeric) -[Password](#rule-password) [Present](#rule-present) [Present If](#rule-present-if) [Present Unless](#rule-present-unless) @@ -1564,14 +1563,6 @@ The field under validation may be `null`. The field under validation must be [numeric](https://www.php.net/manual/en/function.is-numeric.php). - -#### password - -The field under validation must match the authenticated user's password. - -> [!WARNING] -> This rule was renamed to `current_password` with the intention of removing it in Laravel 9. Please use the [Current Password](#rule-current-password) rule instead. - #### present diff --git a/translation-ja/authorization.md b/translation-ja/authorization.md index b875fed..5896b26 100644 --- a/translation-ja/authorization.md +++ b/translation-ja/authorization.md @@ -245,7 +245,7 @@ Laravelは、アクションを認可する2つの主要な方法を提供しま ### インライン認可 -時には、現在認証されているユーザーが、あるアクションを実行する認可を持っているかを、そのアクションに対応する専用のゲートを書かずに判断したいこともあるでしょう。Laravelでは、`Gate::allowIf`や`Gate::denyIf`メソッドを使い、「インライン」での認可チェックを行うことができます。 +時には、現在認証されているユーザーが、あるアクションを実行する認可を持っているかを、そのアクションに対応する専用のゲートを書かずに判断したいこともあるでしょう。Laravelでは、`Gate::allowIf`や`Gate::denyIf`メソッドを使い、「インライン」での認可チェックを行うことができます。インライン認可は、定義した["before"と"after"の認可フック](#intercepting-gate-checks)を実行しません。 ```php use App\Models\User; diff --git a/translation-ja/cashier-paddle.md b/translation-ja/cashier-paddle.md index 839096d..a903d93 100644 --- a/translation-ja/cashier-paddle.md +++ b/translation-ja/cashier-paddle.md @@ -10,6 +10,9 @@ - [Paddle JS](#paddle-js) - [Currency Configuration](#currency-configuration) - [Overriding Default Models](#overriding-default-models) +- [Quickstart](#quickstart) + - [Selling Products](#quickstart-selling-products) + - [Selling Subscriptions](#quickstart-selling-subscriptions) - [Checkout Sessions](#checkout-sessions) - [Overlay Checkout](#overlay-checkout) - [Inline Checkout](#inline-checkout) @@ -192,17 +195,234 @@ After defining your model, you may instruct Cashier to use your custom model via Cashier::useTransactionModel(Transaction::class); } + +## Quickstart + + +### Selling Products + +> [!NOTE] +> Before utilizing Paddle Checkout, you should define Products with fixed prices in your Paddle dashboard. In addition, you should [configure Paddle's webhook handling](#handling-paddle-webhooks). + +Offering product and subscription billing via your application can be intimidating. However, thanks to Cashier and [Paddle's Checkout Overlay](https://www.paddle.com/billing/checkout), you can easily build modern, robust payment integrations. + +To charge customers for non-recurring, single-charge products, we'll utilize Cashier to charge customers with Paddle's Checkout Overlay, where they will provide their payment details and confirm their purchase. Once the payment has been made via the Checkout Overlay, the customer will be redirected to a success URL of your choosing within your application: + + use Illuminate\Http\Request; + + Route::get('/buy', function (Request $request) { + $checkout = $request->user()->checkout('pri_deluxe_album') + ->returnTo(route('dashboard')); + + return view('buy', ['checkout' => $checkout]); + })->name('checkout'); + +As you can see in the example above, we will utilize Cashier's provided `checkout` method to create a checkout object to present the customer the Paddle Checkout Overlay for a given "price identifier". When using Paddle, "prices" refer to [defined prices for specific products](https://developer.paddle.com/build/products/create-products-prices). + +If necessary, the `checkout` method will automatically create a customer in Paddle and connect that Paddle customer record to the corresponding user in your application's database. After completing the checkout session, the customer will be redirected to a dedicated success page where you can display an informational message to the customer. + +In the `buy` view, we will include a button to display the Checkout Overlay. The `paddle-button` Blade component is included with Cashier Paddle; however, you may also [manually render an overlay checkout](#manually-rendering-an-overlay-checkout): + +```html + + Buy Product + +``` + + +#### Providing Meta Data to Paddle Checkout + +When selling products, it's common to keep track of completed orders and purchased products via `Cart` and `Order` models defined by your own application. When redirecting customers to Paddle's Checkout Overlay to complete a purchase, you may need to provide an existing order identifier so that you can associate the completed purchase with the corresponding order when the customer is redirected back to your application. + +To accomplish this, you may provide an array of custom data to the `checkout` method. Let's imagine that a pending `Order` is created within our application when a user begins the checkout process. Remember, the `Cart` and `Order` models in this example are illustrative and not provided by Cashier. You are free to implement these concepts based on the needs of your own application: + + use App\Models\Cart; + use App\Models\Order; + use Illuminate\Http\Request; + + Route::get('/cart/{cart}/checkout', function (Request $request, Cart $cart) { + $order = Order::create([ + 'cart_id' => $cart->id, + 'price_ids' => $cart->price_ids, + 'status' => 'incomplete', + ]); + + $checkout = $request->user()->checkout($order->price_ids) + ->customData(['order_id' => $order->id]); + + return view('billing', ['checkout' => $checkout]); + })->name('checkout'); + +As you can see in the example above, when a user begins the checkout process, we will provide all of the cart / order's associated Paddle price identifiers to the `checkout` method. Of course, your application is responsible for associating these items with the "shopping cart" or order as a customer adds them. We also provide the order's ID to the Paddle Checkout Overlay via the `customData` method. + +Of course, you will likely want to mark the order as "complete" once the customer has finished the checkout process. To accomplish this, you may listen to the webhooks dispatched by Paddle and raised via events by Cashier to store order information in your database. + +To get started, listen for the `TransactionCompleted` event dispatched by Cashier. Typically, you should register the event listener in the `boot` method of one of your application's service providers: + + use App\Listeners\CompleteOrder; + use Illuminate\Support\Facades\Event; + use Laravel\Paddle\Events\TransactionCompleted; + + /** + * Bootstrap any application services. + */ + public function boot(): void + { + Event::listen(TransactionCompleted::class, CompleteOrder::class); + } + +In this example, the `CompleteOrder` listener might look like the following: + + namespace App\Listeners; + + use App\Models\Order; + use Laravel\Cashier\Cashier; + use Laravel\Cashier\Events\TransactionCompleted; + + class CompleteOrder + { + /** + * Handle the incoming Cashier webhook event. + */ + public function handle(TransactionCompleted $event): void + { + $orderId = $event->payload['data']['custom_data']['order_id'] ?? null; + + $order = Order::findOrFail($orderId); + + $order->update(['status' => 'completed']); + } + } + +Please refer to Paddle's documentation for more information on the [data contained by the `transaction.completed` event](https://developer.paddle.com/webhooks/transactions/transaction-completed). + + +### Selling Subscriptions + +> [!NOTE] +> Before utilizing Paddle Checkout, you should define Products with fixed prices in your Paddle dashboard. In addition, you should [configure Paddle's webhook handling](#handling-paddle-webhooks). + +Offering product and subscription billing via your application can be intimidating. However, thanks to Cashier and [Paddle's Checkout Overlay](https://www.paddle.com/billing/checkout), you can easily build modern, robust payment integrations. + +To learn how to sell subscriptions using Cashier and Paddle's Checkout Overlay, let's consider the simple scenario of a subscription service with a basic monthly (`price_basic_monthly`) and yearly (`price_basic_yearly`) plan. These two prices could be grouped under a "Basic" product (`pro_basic`) in our Paddle dashboard. In addition, our subscription service might offer an Expert plan as `pro_expert`. + +First, let's discover how a customer can subscribe to our services. Of course, you can imagine the customer might click a "subscribe" button for the Basic plan on our application's pricing page. This button will invoke a Paddle Checkout Overlay for their chosen plan. To get started, let's initiate a checkout session via the `checkout` method: + + use Illuminate\Http\Request; + + Route::get('/subscribe', function (Request $request) { + $checkout = $request->user()->checkout('price_basic_monthly') + ->returnTo(route('dashboard')); + + return view('subscribe', ['checkout' => $checkout]); + })->name('subscribe'); + +In the `subscribe` view, we will include a button to display the Checkout Overlay. The `paddle-button` Blade component is included with Cashier Paddle; however, you may also [manually render an overlay checkout](#manually-rendering-an-overlay-checkout): + +```html + + Subscribe + +``` + +Now, when the Subscribe button is clicked, the customer will be able to enter their payment details and initiate their subscription. To know when their subscription has actually started (since some payment methods require a few seconds to process), you should also [configure Cashier's webhook handling](#handling-paddle-webhooks). + +Now that customers can start subscriptions, we need to restrict certain portions of our application so that only subscribed users can access them. Of course, we can always determine a user's current subscription status via the `subscribed` method provided by Cashier's `Billable` trait: + +```blade +@if ($user->subscribed()) +

You are subscribed.

+@endif +``` + +We can even easily determine if a user is subscribed to specific product or price: + +```blade +@if ($user->subscribedToProduct('pro_basic')) +

You are subscribed to our Basic product.

+@endif + +@if ($user->subscribedToPrice('price_basic_monthly')) +

You are subscribed to our monthly Basic plan.

+@endif +``` + + +#### Building a Subscribed Middleware + +For convenience, you may wish to create a [middleware](/docs/{{version}}/middleware) which determines if the incoming request is from a subscribed user. Once this middleware has been defined, you may easily assign it to a route to prevent users that are not subscribed from accessing the route: + + user()?->subscribed()) { + // Redirect user to billing page and ask them to subscribe... + return redirect('/subscribe'); + } + + return $next($request); + } + } + +Once the middleware has been defined, you may assign it to a route: + + use App\Http\Middleware\Subscribed; + + Route::get('/dashboard', function () { + // ... + })->middleware([Subscribed::class]); + + +#### Allowing Customers to Manage Their Billing Plan + +Of course, customers may want to change their subscription plan to another product or "tier". In our example from above, we'd want to allow the customer to change their plan from a monthly subscription to a yearly subscription. For this you'll need to implement something like a button that leads to the below route: + + use Illuminate\Http\Request; + + Route::put('/subscription/{price}/swap', function (Request $request, $price) { + $user->subscription()->swap($price); // With "$price" being "price_basic_yearly" for this example. + + return redirect()->route('dashboard'); + })->name('subscription.swap'); + +Besides swapping plans you'll also need to allow your customers to cancel their subscription. Like swapping plans, provide a button that leads to the following route: + + use Illuminate\Http\Request; + + Route::put('/subscription/cancel', function (Request $request, $price) { + $user->subscription()->cancel(); + + return redirect()->route('dashboard'); + })->name('subscription.cancel'); + +And now your subscription will get cancelled at the end of its billing period. + +> [!NOTE] +> As long as you have configured Cashier's webhook handling, Cashier will automatically keep your application's Cashier-related database tables in sync by inspecting the incoming webhooks from Paddle. So, for example, when you cancel a customer's subscription via Paddle's dashboard, Cashier will receive the corresponding webhook and mark the subscription as "cancelled" in your application's database. + ## Checkout Sessions -Most operations to bill customers are performed using "checkouts" via Paddle's [checkout overlay widget](https://developer.paddle.com/build/checkout/build-overlay-checkout) or by utilizing [inline checkout](https://developer.paddle.com/build/checkout/build-branded-inline-checkout). +Most operations to bill customers are performed using "checkouts" via Paddle's [Checkout Overlay widget](https://developer.paddle.com/build/checkout/build-overlay-checkout) or by utilizing [inline checkout](https://developer.paddle.com/build/checkout/build-branded-inline-checkout). Before processing checkout payments using Paddle, you should define your application's [default payment link](https://developer.paddle.com/build/transactions/default-payment-link#set-default-link) in your Paddle checkout settings dashboard. ### Overlay Checkout -Before displaying the checkout overlay widget, you must generate a checkout session using Cashier. A checkout session will inform the checkout widget of the billing operation that should be performed: +Before displaying the Checkout Overlay widget, you must generate a checkout session using Cashier. A checkout session will inform the checkout widget of the billing operation that should be performed: use Illuminate\Http\Request; diff --git a/translation-ja/homestead.md b/translation-ja/homestead.md index e3d9fd6..3aa35c9 100644 --- a/translation-ja/homestead.md +++ b/translation-ja/homestead.md @@ -20,7 +20,7 @@ - [データベース接続](#connecting-to-databases) - [データベースのバックアップ](#database-backups) - [Cronスケジュール設定](#configuring-cron-schedules) - - [MailHogの設定](#configuring-mailhog) + - [Mailpitの設定](#configuring-mailpit) - [Minioの設定](#configuring-minio) - [Laravel Dusk](#laravel-dusk) - [環境の共有](#sharing-your-environment) @@ -58,8 +58,9 @@ Homesteadは、Windows、macOS、Linuxシステムで実行でき、Nginx、PHP
-- Ubuntu 20.04 +- Ubuntu 22.04 - Git +- PHP 8.3 - PHP 8.2 - PHP 8.1 - PHP 8.0 @@ -80,7 +81,7 @@ Homesteadは、Windows、macOS、Linuxシステムで実行でき、Nginx、PHP - Redis - Memcached - Beanstalkd -- Mailhog +- Mailpit - avahi - ngrok - Xdebug @@ -116,7 +117,6 @@ Homesteadは、Windows、macOS、Linuxシステムで実行でき、Nginx、PHP - Grafana - InfluxDB - Logstash -- Mailpit (Mailhogから置き換え) - MariaDB - Meilisearch - MinIO @@ -346,12 +346,10 @@ features: - grafana: true - influxdb: true - logstash: true - - mailpit: true - mariadb: true - meilisearch: true - minio: true - mongodb: true - - mysql: true - neo4j: true - ohmyzsh: true - openresty: true @@ -558,7 +556,7 @@ ports: - **MySQL:** 33060 → フォワード先 3306 - **PostgreSQL:** 54320 → フォワード先 5432 - **MongoDB:** 27017 → フォワード先 27017 -- **Mailhog:** 8025 → フォワード先 8025 +- **Mailpit:** 8025 → フォワード先 8025 - **Minio:** 9600 → フォワード先 9600
@@ -566,7 +564,7 @@ ports: ### PHPバージョン -Homesteadは、同じ仮想マシンで複数のバージョンのPHPを実行するためサポートしています。`Homestead.yaml`ファイル内の特定のサイトに使用するPHPのバージョンを指定できます。使用可能なPHPバージョンは、"5.6", "7.0", "7.1", "7.2", "7.3", "7.4"、"8.0"、"8.1","8.2"(デフォルト)です。 +Homesteadは、同じ仮想マシンで複数のバージョンのPHPを実行するためサポートしています。`Homestead.yaml`ファイル内の特定のサイトに使用するPHPのバージョンを指定できます。使用可能なPHPバージョンは、"5.6", "7.0", "7.1", "7.2", "7.3", "7.4"、"8.0"、"8.1"、"8.2"、"8.3"(デフォルト)です。 ```yaml sites: @@ -587,6 +585,7 @@ php7.4 artisan list php8.0 artisan list php8.1 artisan list php8.2 artisan list +php8.3 artisan list ``` Homestead仮想マシン内から以下のコマンドを実行すれば、CLIで使用するPHPのデフォルトバージョンを変更できます。 @@ -601,6 +600,7 @@ php74 php80 php81 php82 +php83 ``` @@ -636,10 +636,10 @@ sites: サイトのcronジョブは、Homestead仮想マシンの`/etc/cron.d`ディレクトリで定義します。 - -### MailHogの設定 + +### Mailpitの設定 -[MailHog](https://github.com/mailhog/MailHog)を使用すると、実際に受信者にメールを送信しなくても、送信メールを傍受して調査できます。使用するには、以下のメール設定を使用するためアプリケーションの`.env`ファイルを更新します。 +[Mailpit](https://github.com/axllent/mailpit)を使用すると、実際に受信者にメールを送信しなくても、送信メールを傍受して調査できます。使用するには、以下のメール設定を使用するためアプリケーションの`.env`ファイルを更新します。 ```ini MAIL_MAILER=smtp @@ -650,7 +650,7 @@ MAIL_PASSWORD=null MAIL_ENCRYPTION=null ``` -MailHogを設定したら、`http://localhost:8025`にあるMailHogダッシュボードにアクセスできます。 +Mailpitを設定したら、`http://localhost:8025`にある、Mailpitダッシュボードにアクセスできます。 ### Minioの設定 diff --git a/translation-ja/scout.md b/translation-ja/scout.md index f270385..e98b59e 100644 --- a/translation-ja/scout.md +++ b/translation-ja/scout.md @@ -2,8 +2,11 @@ - [イントロダクション](#introduction) - [インストール](#installation) - - [ドライバの事前要件](#driver-prerequisites) - [キュー投入](#queueing) +- [ドライバ動作要件](#driver-prerequisites) + - [Algolia](#algolia) + - [Meilisearch](#meilisearch) + - [Typesense](#typesense) - [設定](#configuration) - [モデルインデックスの設定](#configuring-model-indexes) - [検索可能データの設定](#configuring-searchable-data) @@ -32,7 +35,7 @@ [Laravel Scout](https://github.com/laravel/scout)(Scout、斥候)は、[Eloquentモデル](/docs/{{version}}/eloquent)へ、シンプルなドライバベースのフルテキストサーチを提供します。モデルオブサーバを使い、Scoutは検索インデックスを自動的にEloquentレコードと同期します。 -現在、Scoutは[Algolia](https://www.algolia.com/), [Meilisearch](https://www.meilisearch.com), MySQL/PostgreSQL (`database`) ドライバを用意しています。さらに、Scoutはローカル開発用途に設計された、外部依存やサードパーティサービスを必要としない「コレクション」ドライバも用意しています。加えて、カスタムドライバの作成も簡単で、独自の検索実装でScoutを自由に拡張可能です。 +現在、Scoutは[Algolia](https://www.algolia.com/)、[Meilisearch](https://www.meilisearch.com)、 [Typesense](https://typesense.org)、MySQL/PostgreSQL (`database`)ドライバを用意しています。さらに、Scoutはローカル開発用途に設計した、外部依存やサードパーティサービスを必要としない「コレクション」ドライバも用意しています。加えて、カスタムドライバの作成も簡単で、独自の検索実装でScoutを自由に拡張可能です。 ## インストール @@ -63,11 +66,33 @@ php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider" use Searchable; } + +### キュー投入 + +Scoutを使用するのに厳密には必須ではありませんが、ライブラリを使用する前に[キュードライバ](/docs/{{version}}/queues)の設定を考慮すべきです。キューワーカを実行することで、Scoutはモデル情報を検索インデックスに同期する全ての操作をキューに投入し、アプリケーションのWebインターフェイスのレスポンス時間を大幅に改善できます。 + +キュードライバを設定したら、`config/scout.php`設定ファイルの`queue`オプションの値を`true`へ設定してください。 + + 'queue' => true, + +`queue`オプションを`false`に設定している場合でも、AlgoliaやMeilisearchのようないくつかのScoutドライバは、常に非同期でレコードをインデックスすることを覚えておくことは重要です。つまり、Laravelアプリケーション内でインデックス操作が完了しても、検索エンジン自体には新しいレコードや更新されたレコードがすぐに反映されない可能性があります。 + +Scouジョブで使用する接続とキューを指定するには、`queue`設定オプションを配列で定義してください。 + + 'queue' => [ + 'connection' => 'redis', + 'queue' => 'scout' + ], + +もちろん、Scoutジョブが利用するコネクションやキューをカスタマイズする場合は、そのコネクションやキューでジョブを処理するキューワーカを実行する必要があります。 + + php artisan queue:work redis --queue=scout + -### ドライバの事前要件 +## ドライバ動作要件 -#### Algolia +### Algolia Algoliaドライバを使用する場合、Algolia `id`と`secret`接続情報を`config/scout.php`設定ファイルで設定する必要があります。接続情報を設定し終えたら、Algolia PHP SDKをComposerパッケージマネージャで、インストールする必要があります。 @@ -76,7 +101,7 @@ composer require algolia/algoliasearch-client-php ``` -#### Meilisearch +### Meilisearch [Meilisearch](https://www.meilisearch.com)は、非常に高速なオープンソースの検索エンジンです。ローカルマシンにMeilisearchをインストールする方法がわからない場合は、Laravelの公式サポートのDocker開発環境である[Laravel Sail](/docs/{{version}}/sail#meilisearch)を利用できます。 @@ -101,27 +126,86 @@ Meilisearchの詳細については、[Meilisearchのドキュメント](https:/ > [!WARNING] > Meilisearchを利用しているアプリケーションのScoutをアップグレードする際には、常にMeilisearchサービス自体に[追加の破壊的な変更](https://github.com/meilisearch/Meilisearch/releases)がないか確認する必要があります。 - -### キュー投入 + +### Typesense -厳密にはScoutを使用する必要はありませんが、ライブラリを使用する前に、[キュードライバ](/docs/{{version}}/queues)の設定を強く考慮する必要があります。キューワーカを実行すると、Scoutはモデル情報を検索インデックスに同期するすべての操作をキューに入れることができ、アプリケーションのWebインターフェイスのレスポンス時間が大幅に短縮されます。 +[Typesense](https://typesense.org)は、光のように早いオープンソース検索エンジンで、キーワード検索、セマンティック検索、ジオ検索、ベクトル検索をサポートしています。 -キュードライバを設定したら、`config/scout.php`設定ファイルの`queue`オプションの値を`true`に設定します。 +Typesenseを[セルフホスト](https://typesense.org/docs/guide/install-typesense.html#option-2-local-machine-self-hosting)することも、[Typesense Cloud](https://cloud.typesense.org)を利用することもできます。 - 'queue' => true, +ScoutでTypesenseを使用開始するには、Composerパッケージマネージャにより、Typesense PHP SDKをインストールします。 -`queue`オプションを`false`に設定している場合でも、AlgoliaやMeilisearchなど、一部のScoutドライバは常に非同期でレコードをインデックスしていることを覚えておくことが重要です。つまり、Laravelアプリケーション内でインデックス操作が完了しても、検索エンジン自体には新しいレコードや更新されたレコードがすぐに反映されない可能性があります。 +```shell +composer require typesense/typesense-php +``` -Scoutジョブで利用する接続とキューを指定するには、`queue`設定オプションを配列として定義します。 +次に、アプリケーションの.envファイルで、`SCOUT_DRIVER`環境変数と、TypesenseホストとAPIキーの認証情報を設定します。 - 'queue' => [ - 'connection' => 'redis', - 'queue' => 'scout' +```env +SCOUT_DRIVER=typesense +TYPESENSE_API_KEY=masterKey +TYPESENSE_HOST=localhost +``` + +必要に応じて、インストールのポート、パス、プロトコルを指定することもできます。 + +```env +TYPESENSE_PORT=8108 +TYPESENSE_PATH= +TYPESENSE_PROTOCOL=http +``` + +Typesenseコレクションの追加設定とスキーマ定義は、アプリケーションの`config/scout.php`設定ファイルにあります。Typesenseに関するより詳しい情報は、[Typesenseドキュメント](https://typesense.org/docs/guide/#quick-start)を参照してください。 + + +#### Typesenseに保存するデータの準備 + +Typesenseを利用するとき、Searchableなモデルには、モデルの主キーを文字列へ、作成日時をUNIXタイムスタンプへキャストする、`toSearchableArray`メソッドを定義する必要があります。 + +```php +/** + * モデルのインデックス可能なデータ配列の取得 + * + * @return array + */ +public function toSearchableArray() +{ + return array_merge($this->toArray(),[ + 'id' => (string) $this->id, + 'created_at' => $this->created_at->timestamp, + ]); +} +``` + +Searchableなモデルがソフトデリート可能である場合、アプリケーションの`config/scout.php`設定ファイル内の、モデルに対応するTypesenseスキーマに`__soft_deleted`フィールドを定義する必要があります。 + +```php +User::class => [ + 'collection-schema' => [ + 'fields' => [ + // ... + [ + 'name' => '__soft_deleted', + 'type' => 'int32', + 'optional' => true, + ], + ], ], +], +``` -もちろん、Scoutジョブが利用するコネクションやキューをカスタマイズする場合は、そのコネクションやキューでジョブを処理するキューワーカを実行する必要があります。 + +#### 動的検索パラメータ - php artisan queue:work redis --queue=scout +Typesenseでは、`withSearchParameters`メソッドを使い、検索操作時に[検索パラメータ](https://typesense.org/docs/latest/api/search.html#search-parameters)を動的に変更できます。 + +```php +use App\Models\Todo; + +Todo::search('Groceries')->withSearchParameters([ + 'query_by' => 'title, description' +])->get(); +``` ## 設定 @@ -323,7 +407,7 @@ SCOUT_IDENTIFY=true SCOUT_DRIVER=database ``` -データベースエンジンを好みのドライバに指定したら、[検索可能なデータの設定](#configuring-searchable-data)を行う必要があります。次に、モデルに対して[検索クエリの実行](#searching)を開始します。データベースエンジンを使用する場合、AlgoliaやMeilisearchのように、検索エンジンのインデックス作成は必要ありません。 +データベースエンジンを好みのドライバに指定したら、[検索可能なデータの設定](#configuring-searchable-data)を行う必要があります。次に、モデルに対して[検索クエリの実行](#searching)を開始します。データベースエンジンを使用する場合、AlgoliaやMeilisearch、Typesenseのように、検索エンジンのインデックス作成は必要ありません。 #### データベース検索戦略のカスタマイズ @@ -359,7 +443,7 @@ public function toSearchableArray(): array ### コレクションエンジン -ローカル開発時には、AlgoliaやMeilisearchの検索エンジンを自由に使用することができますが、「コレクション(collection)」エンジンでスタートした方が便利な場合もあります。コレクション・エンジンは、既存データベースからの結果に対して、"where"節とコレクション・フィルタリングを用いて、クエリに該当する検索結果を決定します。このエンジンを使用する場合、Searchableモデルをインデックス化する必要はなく、シンプルにローカル・データベースから検索します。 +ローカル開発時には、AlgoliaやMeilisearch、Typesenseの検索エンジンを自由に使用することができますが、「コレクション(collection)」エンジンでスタートした方が便利な場合もあります。コレクション・エンジンは、既存データベースからの結果に対して、"where"節とコレクション・フィルタリングを用いて、クエリに該当する検索結果を決定します。このエンジンを使用する場合、Searchableモデルをインデックス化する必要はなく、シンプルにローカル・データベースから検索します。 コレクションエンジンを使用するには,環境変数`SCOUT_DRIVER`の値を`collection`に設定するか,アプリケーションの`scout`設定ファイルで`collection`ドライバを直接指定します。 @@ -367,7 +451,7 @@ public function toSearchableArray(): array SCOUT_DRIVER=collection ``` -コレクションドライバを使用ドライバに指定したら、モデルに対して[検索クエリの実行](#searching)を開始できます。コレクションエンジンを使用する場合、AlgoliaやMeilisearchのインデックスのシードに必要なインデックス作成などの検索エンジンのインデックス作成は不要です。 +コレクションドライバを使用ドライバに指定したら、モデルに対して[検索クエリの実行](#searching)を開始できます。コレクションエンジンを使用する場合、AlgoliaやMeilisearch、Typesenseのインデックスのシードに必要なインデックス作成などの検索エンジンのインデックス作成は不要です。 #### データベースエンジンとの違い diff --git a/translation-ja/testing.md b/translation-ja/testing.md index b595e7c..6e5429d 100644 --- a/translation-ja/testing.md +++ b/translation-ja/testing.md @@ -81,7 +81,7 @@ php artisan make:test UserTest --unit --pest } > [!WARNING] -> テストクラスに独自の`setUp`メソッドを定義する場合は、親のクラスの`parent::setUp()`/`parent::tearDown()`を確実に呼び出してください。 +> テストクラスに独自の`setUp`メソッドを定義する場合は、親のクラスの`parent::setUp()`/`parent::tearDown()`を確実に呼び出してください。通常、`parent::setUp()`は自分の `setUp`メソッドの最初で、`parent::tearDown()`は自分の`tearDown`メソッドの最後で呼び出します。 ## テストの実行 diff --git a/translation-ja/validation.md b/translation-ja/validation.md index b771a49..0c00d9e 100644 --- a/translation-ja/validation.md +++ b/translation-ja/validation.md @@ -934,7 +934,6 @@ The credit card number field is required when payment type is credit card. [正規表現不一致](#rule-not-regex) [NULL許可](#rule-nullable) [数値](#rule-numeric) -[パスワード](#rule-password) [存在](#rule-present) [条件一致時存在](#rule-present-if) [条件非一致時存在](#rule-present-unless) @@ -1564,14 +1563,6 @@ PHPの`filter_var`関数を使用する`filter`バリデータは、Laravelに フィールドは[数値](https://www.php.net/manual/ja/function.is-numeric.php)であることをバリデートします。 - -#### password - -フィールドは、認証済みユーザーのパスワードと一致する必要があります。 - -> [!WARNING] -> このルールはLaravel9で削除するため、`current_password`へ名前を変更しました。代わりに[現在のパスワード](#rule-current-password)ルールを使用してください。 - #### present