<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="https://publishpress.com/"
	>

<channel>
	<title>Laravel Archives - Tomoshare</title>
	<atom:link href="https://blog.tomosia.com.vn/tag/laravel/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.tomosia.com.vn/tag/laravel/</link>
	<description>Kênh chia sẻ kiến thức Tomosia Việt Nam</description>
	<lastBuildDate>Thu, 25 Dec 2025 09:28:55 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://blog.tomosia.com.vn/wp-content/uploads/2023/09/cropped-icon-32x32.png</url>
	<title>Laravel Archives - Tomoshare</title>
	<link>https://blog.tomosia.com.vn/tag/laravel/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Laravel Scheduler: Tư duy thiết kế, trade-off và best practices cho hệ thống lớn</title>
		<link>https://blog.tomosia.com.vn/laravel-scheduler-tu-duy-thiet-ke-trade-off-va-best-practices-cho-he-thong-lon/</link>
					<comments>https://blog.tomosia.com.vn/laravel-scheduler-tu-duy-thiet-ke-trade-off-va-best-practices-cho-he-thong-lon/#comments</comments>
		
		<dc:creator><![CDATA[hoa nguyen]]></dc:creator>
		<pubDate>Thu, 25 Dec 2025 09:26:41 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[Scheduler]]></category>
		<category><![CDATA[cronjob]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=3967</guid>

					<description><![CDATA[<p>Nếu bạn đã đi làm vài năm, bạn sẽ thấy &#8220;Scheduler&#8221; không phải chuyện&#160;viết vài dòng&#160;dailyAt(). Nó là&#160;bài&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/laravel-scheduler-tu-duy-thiet-ke-trade-off-va-best-practices-cho-he-thong-lon/">Laravel Scheduler: Tư duy thiết kế, trade-off và best practices cho hệ thống lớn</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Nếu bạn đã đi làm vài năm, bạn sẽ thấy &#8220;Scheduler&#8221; không phải chuyện&nbsp;<em>viết vài dòng&nbsp;<code>dailyAt()</code></em>. Nó là&nbsp;<strong>bài toán reliability + performance + observability</strong>. Sai một ly là: trùng charge, spam notify, kẹt DB lúc 9h, hoặc &#8220;đêm qua không chạy mà không ai biết&#8221;.</p>



<p class="wp-block-paragraph">Bài này chia sẻ theo góc nhìn hệ thống lớn: <strong>ra quyết định kỹ thuật</strong> khi số job tăng nhanh, dữ liệu lớn, nhiều worker, CI/CD liên tục, thậm chí realtime.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="1-nguyên-tắc-số-1-scheduler-phải-nhẹ--việc-nặng-đẩy-qua-queue"><span id="1-nguyen-tac-so-1-scheduler-phai-nhe-viec-nang-day-qua-queue">1. Nguyên tắc số 1: Scheduler phải &#8220;nhẹ&#8221; — việc nặng đẩy qua queue</span></h2>



<p class="wp-block-paragraph"><strong>Tư duy</strong>: Scheduler là &#8220;orchestrator&#8221;, không phải &#8220;executor&#8221;.</p>



<p class="wp-block-paragraph">Scheduler chỉ làm 2 việc:</p>



<ul class="wp-block-list">
<li>Quyết định &#8220;đúng giờ thì trigger cái gì&#8221;</li>



<li>Dispatch nhanh, ghi dấu vết (batch metadata)</li>
</ul>



<p class="wp-block-paragraph">Việc nặng (DB scan, gọi API, gửi notify hàng loạt, reconcile, billing…) → chạy trong&nbsp;<strong>queued jobs</strong>&nbsp;+ nhiều worker.</p>



<p class="wp-block-paragraph"><strong>Trade-off</strong>:</p>



<ul class="wp-block-list">
<li>✅ Ưu: Scale bằng worker, retry/backoff chuẩn, tách tải khỏi scheduler</li>



<li>⚠️ Nhược: Job có thể chạy trễ → phải thiết kế theo &#8220;batch time&#8221; (xem phần 4)</li>
</ul>



<p class="wp-block-paragraph"><strong>Sai lầm thường gặp</strong>: Nhét logic nặng vào scheduler (closure/command) rồi &#8220;đỡ nghẽn&#8221; bằng cách tăng CPU. Đến lúc 100 lịch/ngày thì scheduler thành single-point bottleneck.</p>



<p class="wp-block-paragraph"><strong>Ví dụ</strong>:</p>



<pre class="wp-block-code"><code>&lt;?php

// routes/console.php
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schedule;

// ❌ SAI: Logic nặng trực tiếp trong scheduler
Schedule::call(function () {
    DB::table('recent_users')->chunk(100, function ($users) {
        foreach ($users as $user) {
            // Process payment, send email, update DB...
            // Nếu có 1000 users, scheduler sẽ bị block rất lâu
        }
    });
})->dailyAt('09:00');

// ✅ ĐÚNG: Scheduler chỉ dispatch job
Schedule::job(new ProcessRecentUsersJob)
    ->dailyAt('09:00');</code></pre>



<p class="wp-block-paragraph">Scheduler chỉ trigger đúng giờ, không bao giờ chạy logic business trực tiếp. Worker sẽ xử lý job trong queue.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="2-đúng-một-lần-theo-nghĩa-business--đúng-một-lần-theo-nghĩa-kỹ-thuật"><span id="2-dung-mot-lan-theo-nghia-business-dung-mot-lan-theo-nghia-ky-thuat">2. &#8220;Đúng một lần&#8221; theo nghĩa business &gt; &#8220;đúng một lần&#8221; theo nghĩa kỹ thuật</span></h2>



<p class="wp-block-paragraph">Ở hệ thống lớn, &#8220;at least once&#8221; là mặc định. Scheduler/queue/worker/retry/deploy đều có thể làm job chạy lại.</p>



<p class="wp-block-paragraph"><strong>Best practice</strong>: Thiết kế job theo&nbsp;<strong>idempotent</strong>:</p>



<ul class="wp-block-list">
<li>Chạy 2 lần vẫn ra kết quả đúng</li>



<li>Side-effect (charge/send/update) phải có khóa logic hoặc unique key</li>
</ul>



<p class="wp-block-paragraph">Dùng lock ở&nbsp;<strong>đúng tầng</strong>:</p>



<ul class="wp-block-list">
<li>Tầng scheduler: Chống chồng / chạy một server (khi HA)</li>



<li>Tầng job/business: Lock theo entity/time-window (mới là thứ bảo vệ cuối)</li>
</ul>



<p class="wp-block-paragraph"><strong>Trade-off</strong>:</p>



<ul class="wp-block-list">
<li>Lock nhiều quá → Giảm throughput, dễ nghẽn nếu lock sai granularity</li>



<li>Lock ít quá → Trùng dữ liệu/side-effect</li>
</ul>



<p class="wp-block-paragraph"><strong>Sai lầm thường gặp</strong>: Tin tuyệt đối vào &#8220;chống chồng&#8221; của scheduler rồi bỏ qua idempotency. Một ngày deploy &#8220;đúng lúc&#8221;, bạn sẽ hiểu.</p>



<p class="wp-block-paragraph"><strong>Ví dụ</strong>:</p>



<p class="wp-block-paragraph">Job có idempotency key dựa trên&nbsp;<code>entity_id + batch_time</code>. Concept này áp dụng cho mọi job có side-effect quan trọng. Trong scheduler, bạn chỉ dispatch job với metadata:</p>



<pre class="wp-block-code"><code>&lt;?php

// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::job(new ProcessOrdersJob)
    ->dailyAt('09:00');</code></pre>



<p class="wp-block-paragraph">Job sẽ tự implement idempotency check trong&nbsp;<code>handle()</code>&nbsp;method để đảm bảo không xử lý trùng.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="3-khi-nào-dùng-runinbackground-và-khi-nào-bắt-buộc-dùng-queue"><span id="3-khi-nao-dung-runinbackground-va-khi-nao-bat-buoc-dung-queue">3. Khi nào dùng&nbsp;<code>runInBackground()</code>&nbsp;và khi nào &#8220;bắt buộc&#8221; dùng queue?</span></h2>



<p class="wp-block-paragraph">Tôi coi&nbsp;<code>runInBackground()</code>&nbsp;là&nbsp;<strong>giải pháp tactical</strong>, không phải chiến lược lâu dài.</p>



<p class="wp-block-paragraph"><strong>Dùng&nbsp;<code>runInBackground()</code>&nbsp;khi</strong>:</p>



<ul class="wp-block-list">
<li>Task là command/exec tương đối ngắn</li>



<li>Không cần scale theo tải</li>



<li>Bạn chỉ cần tránh scheduler bị giữ process quá lâu</li>
</ul>



<p class="wp-block-paragraph"><strong>Bắt buộc đưa qua queue khi</strong>:</p>



<ul class="wp-block-list">
<li>Task có thể chạy vài chục giây/phút</li>



<li>Task có thể &#8220;nở&#8221; theo dữ liệu (data grows)</li>



<li>Task có side-effect quan trọng (payment/notify hàng loạt)</li>



<li>Cần retry/backoff, rate-limit, phân ưu tiên</li>
</ul>



<p class="wp-block-paragraph"><strong>Sai lầm thường gặp</strong>: &#8220;Task đang lâu → thêm&nbsp;<code>runInBackground()</code>&#8221; và coi như xong. Thực tế bạn chỉ chuyển nghẽn từ scheduler sang CPU/DB/connections của cùng máy.</p>



<p class="wp-block-paragraph"><strong>Ví dụ</strong>:</p>



<pre class="wp-block-code"><code>&lt;?php

// routes/console.php
use Illuminate\Support\Facades\Schedule;

// ✅ Dùng runInBackground cho command nhẹ, không cần scale
Schedule::command('cache:clear')
    ->hourly()
    ->runInBackground();

Schedule::command('emails:send')
    ->dailyAt('02:00')
    ->runInBackground();

// ✅ Bắt buộc dùng queue cho job có side-effect quan trọng
Schedule::job(new SendOrderConfirmationJob)
    ->dailyAt('09:00'); // Không có runInBackground, vì đã là queued job</code></pre>



<p class="wp-block-paragraph">Chỉ có 2 loại command dùng&nbsp;<code>runInBackground()</code>:</p>



<ol class="wp-block-list">
<li><strong>Maintenance commands</strong> (cleanup, cache) — không ảnh hưởng business</li>



<li><strong>Monitoring commands</strong> — cần chạy nhanh, không cần retry</li>
</ol>



<p class="wp-block-paragraph">Tất cả job business đều qua queue để có retry/backoff/scale.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="4-bài-toán-lớn-nhất-của-hệ-queue-job-chạy-trễ--lệch-cửa-sổ-dữ-liệu"><span id="4-bai-toan-lon-nhat-cua-he-queue-job-chay-tre-%e2%86%92-lech-cua-so-du-lieu">4. Bài toán lớn nhất của hệ queue: Job chạy trễ → lệch cửa sổ dữ liệu</span></h2>



<p class="wp-block-paragraph">Đây là điểm phân biệt hệ &#8220;chạy được&#8221; và hệ &#8220;chạy đúng&#8221;.</p>



<p class="wp-block-paragraph"><strong>Vấn đề</strong>:</p>



<ul class="wp-block-list">
<li>Scheduler trigger 09:00, worker chạy 09:04</li>



<li>Nếu job query theo <code>now()</code> lúc 09:04, bạn vừa:
<ul class="wp-block-list">
<li>Miss dữ liệu 09:00–09:04 (tùy window)</li>



<li>Hoặc duplicate với batch trước</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"><strong>Giải pháp</strong>: Scheduler&nbsp;<strong>đóng dấu batch time</strong>&nbsp;ngay lúc dispatch (tôi hay gọi&nbsp;<code>scheduledAt</code>/<code>batchAt</code>). Job luôn dùng&nbsp;<code>scheduledAt</code>&nbsp;để:</p>



<ul class="wp-block-list">
<li>Tính window dữ liệu</li>



<li>Log/audit theo batch</li>



<li>Tạo idempotency key</li>
</ul>



<p class="wp-block-paragraph"><strong>Trade-off</strong>:</p>



<ul class="wp-block-list">
<li>Tốn thêm metadata, thêm &#8220;kỷ luật&#8221; trong code</li>



<li>Đổi lại: Batch chạy trễ vẫn <strong>đúng cửa sổ</strong>, dễ đối soát, dễ replay theo batch</li>
</ul>



<p class="wp-block-paragraph"><strong>Ví dụ — Pattern batch timestamp</strong>:</p>



<p class="wp-block-paragraph">Concept: Scheduler đóng dấu batch time ngay lúc dispatch. Job nhận batch time và dùng để tính time window, không dùng&nbsp;<code>now()</code>.</p>



<p class="wp-block-paragraph"><strong>Sử dụng trong Laravel 12</strong>:</p>



<pre class="wp-block-code"><code>&lt;?php

// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::job(new ProcessOrdersJob)
    ->dailyAt('09:00');</code></pre>



<p class="wp-block-paragraph">Job sẽ nhận&nbsp;<code>scheduledAt</code>&nbsp;từ scheduler event và dùng để query đúng time window.</p>



<p class="wp-block-paragraph"><strong>Ví dụ với sub-minute scheduling trong Laravel 12</strong>:</p>



<p class="wp-block-paragraph">Theo&nbsp;<a href="https://laravel.com/docs/12.x/scheduling#sub-minute-scheduled-tasks">Laravel 12.x Sub-Minute Scheduled Tasks</a>:</p>



<pre class="wp-block-code"><code>&lt;?php

// routes/console.php
use Illuminate\Support\Facades\Schedule;

// Laravel 12 hỗ trợ sub-minute scheduling
Schedule::call(function () {
    // Process tasks every 30 seconds
})->everyThirtySeconds();</code></pre>



<p class="wp-block-paragraph"><strong>Lợi ích</strong>:</p>



<ul class="wp-block-list">
<li>Job chạy trễ 3 phút vẫn query đúng cửa sổ 09:00–09:01</li>



<li>Dễ đối soát: &#8220;Batch 09:00 đã xử lý bao nhiêu records?&#8221;</li>



<li>Dễ replay: &#8220;Chạy lại batch 09:00&#8221; → chỉ cần tạo job với <code>jobCreatedAt = 09:00</code></li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="5-tách-workload-shape-phân-queue-theo-ưu-tiên-tránh-job-rác-ăn-tài-nguyên-job-sống-còn"><span id="5-tach-workload-shape-phan-queue-theo-uu-tien-tranh-job-rac-an-tai-nguyen-job-song-con">5. Tách &#8220;workload shape&#8221;: Phân queue theo ưu tiên, tránh job &#8220;rác&#8221; ăn tài nguyên job &#8220;sống còn&#8221;</span></h2>



<p class="wp-block-paragraph">Một hệ thống lớn sẽ có job kiểu:</p>



<ul class="wp-block-list">
<li><strong>Critical</strong>: Billing, payment, cancel, inventory, security</li>



<li><strong>Default</strong>: Vận hành</li>



<li><strong>Low</strong>: Marketing, remind, digest</li>
</ul>



<p class="wp-block-paragraph"><strong>Best practice</strong>: Tách queue theo priority, scale worker theo queue. Đặt rule: Job low không bao giờ được làm chậm job critical.</p>



<p class="wp-block-paragraph"><strong>Trade-off</strong>:</p>



<ul class="wp-block-list">
<li>Nhiều queue → Config vận hành phức tạp hơn (supervisor/horizon)</li>



<li>Nhưng nếu không tách, bạn sẽ gặp kiểu &#8220;19h campaign bắn notify&#8221; làm nghẽn payment</li>
</ul>



<p class="wp-block-paragraph"><strong>Lưu ý</strong>: Trong scheduler, bạn có thể chỉ định queue khi schedule job:</p>



<p class="wp-block-paragraph">Theo&nbsp;<a href="https://laravel.com/docs/12.x/scheduling#scheduling-queued-jobs">Laravel 12.x Scheduling Queued Jobs</a>, method&nbsp;<code>job()</code>&nbsp;nhận queue name làm tham số thứ 2:</p>



<pre class="wp-block-code"><code>&lt;?php

// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::job(new SendOrderConfirmationJob, 'critical')
    ->dailyAt('09:00');</code></pre>



<p class="wp-block-paragraph">Hoặc nếu job class đã có property&nbsp;<code>$queue</code>, scheduler sẽ tự động dùng queue đó.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="6-thundering-herd-lúc-tròn-giờ-kẻ-thù-của-db-và-api"><span id="6-thundering-herd-luc-tron-gio-ke-thu-cua-db-va-api">6. &#8220;Thundering herd&#8221; lúc tròn giờ: Kẻ thù của DB và API</span></h2>



<p class="wp-block-paragraph">Hệ thống lớn rất hay bị &#8220;dồn lịch&#8221; vào 00:00, 09:00, 12:00, 19:00…</p>



<p class="wp-block-paragraph"><strong>Best practice</strong>:</p>



<ul class="wp-block-list">
<li><strong>Stagger</strong>: Dàn đều theo phút/giây</li>



<li>Nếu bắt buộc tròn giờ: Chia nhỏ thành nhiều job chunk, có rate-limit/backoff</li>



<li>Không quét toàn bảng: Dùng cursor/chunk theo index, watermark theo batch</li>
</ul>



<p class="wp-block-paragraph"><strong>Sai lầm thường gặp</strong>: Một job &#8220;tổng hợp cuối ngày&#8221; chạy 00:00 quét cả bảng 50 triệu dòng. Đêm đó DB chết, sáng không ai biết vì không có alert.</p>



<p class="wp-block-paragraph"><strong>Ví dụ — Stagger pattern trong scheduler</strong>:</p>



<pre class="wp-block-code"><code>&lt;?php

// routes/console.php
use Illuminate\Support\Facades\Schedule;

// Dàn đều theo phút để tránh thundering herd
$times = &#91;'9:03', '10:03', '11:03', '12:03', '13:03', '14:03', '15:03', '16:03', '17:03', '18:03', '19:03', '20:03', '21:03'];

foreach ($times as $time) {
    Schedule::job(new ProcessHourlyTaskJob)
        ->at($time);
}</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="7-observability-là-bắt-buộc-không-ai-biết-scheduler-fail--thất-bại-hệ-thống"><span id="7-observability-la-bat-buoc-khong-ai-biet-scheduler-fail-that-bai-he-thong">7. Observability là bắt buộc: &#8220;Không ai biết scheduler fail&#8221; = thất bại hệ thống</span></h2>



<p class="wp-block-paragraph">Scheduler fail nguy hiểm vì nó&nbsp;<strong>âm thầm</strong>.</p>



<p class="wp-block-paragraph"><strong>Best practice</strong>:</p>



<ul class="wp-block-list">
<li>Log theo batch (scheduledAt, job name, duration, result)</li>



<li>Có alert khi fail (hook/event/ping tùy hệ)</li>



<li>Có &#8220;schedule inventory&#8221;: Định kỳ audit lịch chạy (ít nhất kiểm lịch sau deploy)</li>
</ul>



<p class="wp-block-paragraph"><strong>Trade-off</strong>:</p>



<ul class="wp-block-list">
<li>Thêm log/metrics → Tốn công + tốn storage</li>



<li>Nhưng thiếu nó thì khi sự cố xảy ra, bạn mất nhiều giờ &#8220;đào mộ&#8221;</li>
</ul>



<p class="wp-block-paragraph"><strong>Ví dụ — Scheduler hooks trong Laravel 12</strong>:</p>



<p class="wp-block-paragraph">Theo&nbsp;<a href="https://laravel.com/docs/12.x/scheduling#task-hooks">Laravel 12.x Task Hooks</a>:</p>



<pre class="wp-block-code"><code>&lt;?php

// routes/console.php
use Illuminate\Support\Facades\Schedule;

Schedule::command('emails:send')
    ->daily()
    ->before(function () {
        // The task is about to execute...
    })
    ->after(function () {
        // The task has executed...
    })
    ->onSuccess(function () {
        // The task succeeded...
    })
    ->onFailure(function () {
        // The task failed...
    });</code></pre>



<p class="wp-block-paragraph"><strong>Scheduler setup</strong>:</p>



<pre class="wp-block-code"><code># Cron entry
* * * * * cd /path-to-app &amp;&amp; php artisan schedule:run >> /dev/null 2>&amp;1</code></pre>



<p class="wp-block-paragraph"><strong>Kiểm tra lịch chạy</strong>:</p>



<pre class="wp-block-code"><code># Laravel 12: Xem tất cả scheduled tasks
php artisan schedule:list</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="8-cicd--deploy-đừng-để-deploy-tạo-ra-double-run--half-run"><span id="8-ci-cd-deploy-dung-de-deploy-tao-ra-double-run-half-run">8. CI/CD &amp; Deploy: Đừng để deploy tạo ra double-run / half-run</span></h2>



<p class="wp-block-paragraph">Ở môi trường deploy liên tục, scheduler/worker cần &#8220;graceful&#8221;:</p>



<p class="wp-block-paragraph"><strong>Best practice</strong>:</p>



<ul class="wp-block-list">
<li>Tránh chạy song song 2 version job logic cho cùng một batch</li>



<li>Worker restart có kiểm soát; job quan trọng có idempotency key để chịu được retry/duplicate</li>



<li>Nếu hệ HA nhiều scheduler node: Phải có chiến lược &#8220;one server&#8221; + shared lock store</li>
</ul>



<p class="wp-block-paragraph"><strong>Sai lầm thường gặp</strong>: Deploy xong &#8220;mọi thứ xanh&#8221;, nhưng lịch 09:00 bị chạy 2 lần vì 2 scheduler node cùng tick.</p>



<p class="wp-block-paragraph"><strong>Ví dụ — Laravel 12&nbsp;<code>onOneServer()</code></strong>:</p>



<p class="wp-block-paragraph">Theo&nbsp;<a href="https://laravel.com/docs/12.x/scheduling#running-tasks-on-one-server">Laravel 12.x Running Tasks on One Server</a>:</p>



<pre class="wp-block-code"><code>&lt;?php

// routes/console.php
use Illuminate\Support\Facades\Schedule;

// Nếu có nhiều scheduler server, dùng onOneServer() để chạy chỉ trên 1 server
Schedule::command('emails:send')
    ->daily()
    ->onOneServer(); // Chỉ chạy trên 1 server, dùng cache để lock</code></pre>



<p class="wp-block-paragraph"><strong>Lưu ý</strong>: Job vẫn phải idempotent vì:</p>



<ul class="wp-block-list">
<li>Retry khi fail</li>



<li>Deploy có thể làm job chạy lại</li>



<li>Worker restart có thể làm job chạy lại</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="9-tổ-chức-code-khi-kernelphp-phình-to"><span id="9-to-chuc-code-khi-kernel-php-phinh-to">9. Tổ chức code: Khi Kernel.php &#8220;phình to&#8221;</span></h2>



<p class="wp-block-paragraph">Khi số lượng lịch tăng,&nbsp;<code>Kernel.php</code>&nbsp;sẽ rất dài (có thể lên 300+ lines).</p>



<p class="wp-block-paragraph"><strong>Best practice — Laravel 12</strong>: Tách helper functions theo domain để dễ maintain:</p>



<p class="wp-block-paragraph">Theo&nbsp;<a href="https://laravel.com/docs/12.x/scheduling#defining-schedules">Laravel 12.x Defining Schedules</a>, bạn có thể định nghĩa trong&nbsp;<code>routes/console.php</code>&nbsp;và tách thành helper functions:</p>



<pre class="wp-block-code"><code>&lt;?php

// routes/console.php
use Illuminate\Support\Facades\Schedule;

// Tách theo domain để dễ maintain
schedulePaymentTasks();
scheduleNotificationTasks();
scheduleCleanupTasks();

function schedulePaymentTasks(): void
{
    Schedule::command('payments:process')
        ->dailyAt('09:00');

    Schedule::command('payments:retry')
        ->dailyAt('14:00');
}

function scheduleNotificationTasks(): void
{
    Schedule::command('notifications:send')
        ->hourly();

    Schedule::command('notifications:digest')
        ->dailyAt('20:00');
}

function scheduleCleanupTasks(): void
{
    Schedule::command('cache:clear')
        ->hourly()
        ->runInBackground();
}</code></pre>



<p class="wp-block-paragraph">Hoặc dùng&nbsp;<code>withSchedule</code>&nbsp;trong&nbsp;<code>bootstrap/app.php</code>&nbsp;và tách thành methods:</p>



<pre class="wp-block-code"><code>&lt;?php

// bootstrap/app.php
use Illuminate\Console\Scheduling\Schedule;

->withSchedule(function (Schedule $schedule) {
    schedulePaymentTasks($schedule);
    scheduleNotificationTasks($schedule);
    scheduleCleanupTasks($schedule);
});

function schedulePaymentTasks(Schedule $schedule): void
{
    $schedule->command('payments:process')->dailyAt('09:00');
    $schedule->command('payments:retry')->dailyAt('14:00');
}</code></pre>



<p class="wp-block-paragraph"><strong>Lợi ích</strong>:</p>



<ul class="wp-block-list">
<li>Dễ review: Mỗi function = 1 domain</li>



<li>Dễ test: Có thể test từng domain riêng</li>



<li>Dễ ownership: Team có thể own từng domain</li>



<li>Tránh Kernel.php phình to: Code nằm trong <code>routes/console.php</code> hoặc helper functions</li>
</ul>



<p class="wp-block-paragraph"><strong>Schedule Groups — Laravel 12</strong>:</p>



<p class="wp-block-paragraph">Theo&nbsp;<a href="https://laravel.com/docs/12.x/scheduling#schedule-groups">Laravel 12.x Schedule Groups</a>, bạn có thể nhóm các tasks có cùng cấu hình để tránh lặp lại code:</p>



<pre class="wp-block-code"><code>&lt;?php

// routes/console.php
use Illuminate\Support\Facades\Schedule;

// ❌ SAI: Lặp lại cấu hình cho từng task
Schedule::command('emails:send')
    ->daily()
    ->onOneServer()
    ->timezone('America/New_York');

Schedule::command('emails:prune')
    ->daily()
    ->onOneServer()
    ->timezone('America/New_York');

// ✅ ĐÚNG: Dùng Schedule Groups để nhóm tasks có cùng cấu hình
Schedule::daily()
    ->onOneServer()
    ->timezone('America/New_York')
    ->group(function () {
        Schedule::command('emails:send');
        Schedule::command('emails:prune');
    });</code></pre>



<p class="wp-block-paragraph"><strong>Lợi ích của Schedule Groups</strong>:</p>



<ul class="wp-block-list">
<li><strong>Giảm lặp lại code</strong>: Không cần lặp lại <code>onOneServer()</code>, <code>timezone()</code>, <code>withoutOverlapping()</code> cho từng task</li>



<li><strong>Dễ maintain</strong>: Thay đổi cấu hình một lần áp dụng cho cả nhóm</li>



<li><strong>Tăng tính nhất quán</strong>: Đảm bảo tất cả tasks trong nhóm có cùng cấu hình</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="10-timezone-handling-luôn-nhất-quán"><span id="10-timezone-handling-luon-nhat-quan">10. Timezone handling: Luôn nhất quán</span></h2>



<p class="wp-block-paragraph"><strong>Best practice</strong>: Cố định timezone theo business, không dùng server timezone.&nbsp;<strong>Nguyên tắc</strong>: Tất cả scheduled tasks phải dùng cùng một business timezone để đảm bảo tính nhất quán.</p>



<p class="wp-block-paragraph"><strong>Ví dụ — Laravel 12 timezone</strong>:</p>



<p class="wp-block-paragraph">Theo&nbsp;<a href="https://laravel.com/docs/12.x/scheduling#timezones">Laravel 12.x Scheduling Timezones</a>, có 2 cách set timezone:</p>



<p class="wp-block-paragraph"><strong>Cách 1: Set timezone trong config (khuyến nghị)</strong>:</p>



<p class="wp-block-paragraph">Khi tất cả tasks dùng cùng business timezone, thêm&nbsp;<code>schedule_timezone</code>&nbsp;vào&nbsp;<code>config/app.php</code>:</p>



<pre class="wp-block-code"><code>&lt;?php

// config/app.php
return &#91;
    'timezone' => 'UTC', // Application timezone

    'schedule_timezone' => 'Asia/Tokyo', // Business timezone cho scheduled tasks
];</code></pre>



<p class="wp-block-paragraph">Với cấu hình này, tất cả scheduled tasks sẽ tự động dùng timezone&nbsp;<code>Asia/Tokyo</code>&nbsp;trừ khi được ghi đè bởi method&nbsp;<code>timezone()</code>&nbsp;trong từng task cụ thể.</p>



<p class="wp-block-paragraph"><strong>Cách 2: Set timezone cho từng task riêng</strong>:</p>



<p class="wp-block-paragraph">Chỉ định timezone cho task cụ thể bằng method&nbsp;<code>timezone()</code>:</p>



<pre class="wp-block-code"><code>&lt;?php

// routes/console.php
use Illuminate\Support\Facades\Schedule;

// Set timezone cho task cụ thể (ghi đè config)
Schedule::command('report:generate')
    ->timezone('America/New_York')
    ->at('2:00');</code></pre>



<p class="wp-block-paragraph"><strong>Lưu ý quan trọng về DST (Daylight Saving Time)</strong>:</p>



<p class="wp-block-paragraph">Theo&nbsp;<a href="https://laravel.com/docs/12.x/scheduling#timezones">Laravel 12.x Scheduling Timezones</a>, một số timezone sử dụng DST có thể ảnh hưởng đến thời gian thực thi. Khi DST thay đổi, task có thể chạy 2 lần hoặc không chạy.&nbsp;<strong>Nên tránh dùng timezone có DST khi có thể</strong>.</p>



<p class="wp-block-paragraph"><strong>Nguyên tắc áp dụng</strong>:</p>



<ul class="wp-block-list">
<li>✅ <strong>Nên</strong>: Set timezone một lần trong <code>config/app.php</code> với key <code>schedule_timezone</code> nếu tất cả tasks dùng cùng business timezone</li>



<li>⚠️ <strong>Tránh</strong>: Set timezone cho từng task riêng lẻ → dễ quên, dễ sai, khó maintain</li>



<li>⚠️ <strong>Tránh</strong>: Dùng timezone có DST → có thể ảnh hưởng đến thời gian thực thi khi DST thay đổi</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="kết-luận-framework-cho-quyết-định-kỹ-thuật"><span id="ket-luan-framework-cho-quyet-dinh-ky-thuat">Kết luận: Framework cho quyết định kỹ thuật</span></h2>



<p class="wp-block-paragraph">Khi thêm một scheduled task mới, tôi tự hỏi 6 câu:</p>



<ol class="wp-block-list">
<li><strong>Task này có side-effect quan trọng không?</strong> → Nếu có → Idempotent + audit batch</li>



<li><strong>Dữ liệu tăng thì task tăng theo tuyến nào?</strong> → Nếu O(N) theo bảng lớn → Phải có watermark/chunk/index</li>



<li><strong>Chạy trễ có làm sai cửa sổ dữ liệu không?</strong> → Nếu có → Cần <code>scheduledAt/batchAt</code></li>



<li><strong>Có được phép chạy song song không?</strong> → Nếu không → Overlap guard + lock theo business key</li>



<li><strong>Nó thuộc priority nào?</strong> → Nếu không critical → Đừng để nó chạy chung queue với critical</li>



<li><strong>Fail thì ai biết, trong bao lâu?</strong> → Nếu câu trả lời mơ hồ → Bổ sung observability trước</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading" id="checklist-áp-dụng"><span id="checklist-ap-dung">Checklist áp dụng</span></h2>



<ul class="wp-block-list">
<li> Scheduler chỉ dispatch queued jobs, không chạy logic nặng</li>



<li> Tất cả job có side-effect đều idempotent</li>



<li> Job dùng <code>batchTime/scheduledAt</code> để tính time window, không dùng <code>now()</code></li>



<li> Job dùng <code>chunkById</code> hoặc cursor pagination cho data lớn</li>



<li> Job có stagger/rate-limit khi gọi external API</li>



<li> Job log theo batch time để dễ đối soát</li>



<li> Scheduler có helper methods theo domain, không phình to <code>schedule()</code></li>



<li> Timezone nhất quán: Business timezone, không dùng server timezone</li>



<li> Queue được phân priority (critical/default/low)</li>



<li> Có alert khi scheduler/job fail</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Tài liệu tham khảo</strong>:&nbsp;<a href="https://laravel.com/docs/12.x/scheduling#main-content">Laravel 12.x Task Scheduling</a></p>
<p>The post <a href="https://blog.tomosia.com.vn/laravel-scheduler-tu-duy-thiet-ke-trade-off-va-best-practices-cho-he-thong-lon/">Laravel Scheduler: Tư duy thiết kế, trade-off và best practices cho hệ thống lớn</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/laravel-scheduler-tu-duy-thiet-ke-trade-off-va-best-practices-cho-he-thong-lon/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>Sort và filter dữ liệu dễ dàng hơn với Laravel Purity</title>
		<link>https://blog.tomosia.com.vn/sort-va-filter-du-lieu-de-dang-hon-voi-laravel-purity/</link>
					<comments>https://blog.tomosia.com.vn/sort-va-filter-du-lieu-de-dang-hon-voi-laravel-purity/#comments</comments>
		
		<dc:creator><![CDATA[Thien Tran]]></dc:creator>
		<pubDate>Sun, 10 Dec 2023 14:59:39 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Laravel]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=2484</guid>

					<description><![CDATA[<p>Giới thiệu về Laravel Purity Laravel purity là một thư viện hỗ trợ filter và sort data một&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/sort-va-filter-du-lieu-de-dang-hon-voi-laravel-purity/">Sort và filter dữ liệu dễ dàng hơn với Laravel Purity</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 id="gioi-thieu-ve-laravel-purity" class="wp-block-heading">Giới thiệu về Laravel Purity</h2>



<p class="wp-block-paragraph">Laravel purity là một thư viện hỗ trợ filter và sort data một cách dễ dàng đơn giản hỗ trợ trực tiếp cho laravel framework. Để biết được sự lợi hại của thư viện này. Hãy cùng mình mò mẫm nó nhé. Let&#8217;s gooooooo !!!</p>



<h2 id="dat-van-de" class="wp-block-heading">Đặt vấn đề</h2>



<p class="wp-block-paragraph">Khi chúng ta viết api để filter nhiều giá trị cùng một lúc thì service của chúng ta sẽ khá dài dòng và rườm rà. Để viết ra một hàm filter dùng chung thì sẽ tốn khá nhiều thời gian và chất xám. Vì vậy thư viện này sinh ra với mục đích tối giản hơn về cách filter và sort dữ liệu.</p>



<h2 id="loi-ich-khi-su-dung" class="wp-block-heading">Lợi ích khi sử dụng</h2>



<p class="wp-block-paragraph">Khi chúng ta viết một cách bình thường:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="public function index(Request $request)
{
    $query = Post::query();

    // Lọc theo tiêu đề
    if ($request-&gt;has('title')) {
        $query-&gt;where('title', 'like', '%' . $request-&gt;input('title') . '%');
    }

    // Lọc theo nội dung (content)
    if ($request-&gt;has('content')) {
        $query-&gt;where('content', 'like', '%' . $request-&gt;input('content') . '%');
    }

    // Lọc theo ngày xuất bản (published_at)
    if ($request-&gt;has('published_at')) {
        $query-&gt;whereDate('published_at', '=', $request-&gt;input('published_at'));
    }

    $posts = $query-&gt;get();

    return response()-&gt;json($posts);
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">index</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1; font-style: italic">Request</span><span style="color: #F6F6F4"> $request)</span></span>
<span class="line"><span style="color: #F6F6F4">{</span></span>
<span class="line"><span style="color: #F6F6F4">    $query </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Post</span><span style="color: #F286C4">::</span><span style="color: #62E884">query</span><span style="color: #F6F6F4">();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Lọc theo tiêu đề</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">if</span><span style="color: #F6F6F4"> ($request</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">has</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">title</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">)) {</span></span>
<span class="line"><span style="color: #F6F6F4">        $query</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">where</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">title</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">, </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">like</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">, </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">%</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">.</span><span style="color: #F6F6F4"> $request</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">input</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">title</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">) </span><span style="color: #F286C4">.</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">%</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">);</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Lọc theo nội dung (content)</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">if</span><span style="color: #F6F6F4"> ($request</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">has</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">content</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">)) {</span></span>
<span class="line"><span style="color: #F6F6F4">        $query</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">where</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">content</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">, </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">like</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">, </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">%</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">.</span><span style="color: #F6F6F4"> $request</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">input</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">content</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">) </span><span style="color: #F286C4">.</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">%</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">);</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Lọc theo ngày xuất bản (published_at)</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">if</span><span style="color: #F6F6F4"> ($request</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">has</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">published_at</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">)) {</span></span>
<span class="line"><span style="color: #F6F6F4">        $query</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">whereDate</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">published_at</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">, </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">=</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">, $request</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">input</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">published_at</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">));</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    $posts </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $query</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">get</span><span style="color: #F6F6F4">();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">response</span><span style="color: #F6F6F4">()</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">json</span><span style="color: #F6F6F4">($posts);</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Khi dùng thư viện trên </p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="public function index(Request $request)
{
    $query = Post::filter()-&gt;get();

    return response()-&gt;json($posts);
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">index</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1; font-style: italic">Request</span><span style="color: #F6F6F4"> $request)</span></span>
<span class="line"><span style="color: #F6F6F4">{</span></span>
<span class="line"><span style="color: #F6F6F4">    $query </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Post</span><span style="color: #F286C4">::</span><span style="color: #62E884">filter</span><span style="color: #F6F6F4">()</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">get</span><span style="color: #F6F6F4">();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">response</span><span style="color: #F6F6F4">()</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">json</span><span style="color: #F6F6F4">($posts);</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph"><strong><em>Thật là ngắn gọn và súc tích phải không nào </em></strong>!!!</p>



<h2 id="cach-cai-dat-va-su-dung" class="wp-block-heading">Cách cài đặt và sử dụng</h2>



<p class="wp-block-paragraph">Mở terminal của project lên và cài bằng composer nhé: </p>



<pre class="wp-block-code"><code>composer require abbasudo/laravel-purity </code></pre>



<pre class="wp-block-code"><code>php artisan vendor:publish --tag=purity </code></pre>



<p class="wp-block-paragraph">Lệnh này để publish thư mục `config/purity` cho phép chúng ta có thể custom được filter mà chúng ta muốn.</p>



<p class="wp-block-paragraph">Vậy là thư viện đã sẵn sàng để sử dụng. Tiếp theo hãy tìm tới Model mà bạn muốn filter nhé. Ở đây mình đang filter cho Model Post</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="&lt;?php

namespace App\Models;

use Abbasudo\Purity\Traits\Filterable;
use Abbasudo\Purity\Traits\Sortable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;
    use Filterable;
    use Sortable;

    protected $filterFields = [
        'id',
        'title',
        'content',
        'published_at',
        'category_id',
        'category'
    ];

    public function category()
    {
        return $this-&gt;belongsTo(Category::class);
    }
}
" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">&lt;?</span><span style="color: #BF9EEE">php</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">namespace</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">App</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Models</span><span style="color: #F6F6F4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">use</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Abbasudo</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Purity</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Traits</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Filterable</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F286C4">use</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Abbasudo</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Purity</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Traits</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Sortable</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F286C4">use</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Illuminate</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Database</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Eloquent</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Factories</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">HasFactory</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F286C4">use</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Illuminate</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Database</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Eloquent</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Model</span><span style="color: #F6F6F4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Post</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">extends</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Model</span></span>
<span class="line"><span style="color: #F6F6F4">{</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">use</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">HasFactory</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">use</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Filterable</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">use</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Sortable</span><span style="color: #F6F6F4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">protected</span><span style="color: #F6F6F4"> $filterFields </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> [</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">id</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">title</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">content</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">published_at</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">category_id</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">category</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #F6F6F4">    ];</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">category</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">    {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">belongsTo</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1; font-style: italic">Category</span><span style="color: #F286C4">::class</span><span style="color: #F6F6F4">);</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Các bạn chỉ cần Use Filterable và Sortable của thư viện để sử dụng. Mảng $filterFields là những giá trị mình muốn filter nhé. Ở đây mình có Category là relation của Post.</p>



<p class="wp-block-paragraph">Tiếp theo trong function của mình dùng câu lệnh này nữa là oke nhoé :))</p>



<pre class="wp-block-code"><code>return Post::sort()->filter()->with('category')->get();</code></pre>



<p class="wp-block-paragraph">Đây là một url để chúng ta filters nhé</p>



<pre class="wp-block-code"><code>GET /api/posts?filters&#91;field]&#91;operator]=value</code></pre>



<p class="wp-block-paragraph">Dưới đây là một số operator mà thư viện hỗ trợ</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="799" height="1024" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/12/Screenshot-2023-12-10-at-4.38.25-PM-799x1024.png" alt="" class="wp-image-2485" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/12/Screenshot-2023-12-10-at-4.38.25-PM-799x1024.png 799w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/Screenshot-2023-12-10-at-4.38.25-PM-234x300.png 234w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/Screenshot-2023-12-10-at-4.38.25-PM-768x984.png 768w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/Screenshot-2023-12-10-at-4.38.25-PM-380x487.png 380w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/Screenshot-2023-12-10-at-4.38.25-PM-800x1025.png 800w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/Screenshot-2023-12-10-at-4.38.25-PM.png 1118w" sizes="(max-width: 799px) 100vw, 799px" /></figure>



<h2 id="test-ket-qua" class="wp-block-heading">Test kết quả</h2>



<p class="wp-block-paragraph">Dưới đây là video mình test bằng Postman. Các bạn có thể test thử xem nhé!</p>



<figure class="wp-block-video"><video height="1740" style="aspect-ratio: 2866 / 1740;" width="2866" controls src="http://blog.tomosia.com.vn/wp-content/uploads/2023/12/demo-purity.mov"></video></figure>



<h2 id="tong-ket" class="wp-block-heading">Tổng kết</h2>



<p class="wp-block-paragraph">Đây là một thư viện khá hay mà mình vô tình đọc được. Ở trên mình tập trung nhiều cho phần <strong><em>filter</em></strong>, còn <strong><em>sort</em></strong> cũng khá hay, các bạn khám phá thử xem nhá.</p>



<p class="wp-block-paragraph">Hy vọng các bạn cảm thấy nó thú vị và có thể áp dụng vào dự án nếu có những tính năng tương tự. Cảm ơn mọi người đã dành thời gian đọc ạ ☺️☺️☺️</p>



<p class="wp-block-paragraph"><em>Nguồn:</em> </p>



<ul class="wp-block-list">
<li>Trang chủ của thư viện <a href="https://abbasudo.github.io/laravel-purity/">https://abbasudo.github.io/laravel-purity/</a></li>



<li><a href="https://laravel-news.com/filter-api-responses-with-laravel-purity?ref=dailydev">https://laravel-news.com/filter-api-responses-with-laravel-purity?ref=dailydev</a></li>
</ul>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://blog.tomosia.com.vn/sort-va-filter-du-lieu-de-dang-hon-voi-laravel-purity/">Sort và filter dữ liệu dễ dàng hơn với Laravel Purity</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/sort-va-filter-du-lieu-de-dang-hon-voi-laravel-purity/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		<enclosure url="http://blog.tomosia.com.vn/wp-content/uploads/2023/12/demo-purity.mov" length="38785537" type="video/quicktime" />

			</item>
		<item>
		<title>SOLID Principles</title>
		<link>https://blog.tomosia.com.vn/solid-principles/</link>
					<comments>https://blog.tomosia.com.vn/solid-principles/#comments</comments>
		
		<dc:creator><![CDATA[admin_tomosia]]></dc:creator>
		<pubDate>Mon, 04 Dec 2023 02:05:40 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Kinh nghiệm]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[SOLID]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=2208</guid>

					<description><![CDATA[<p>Các nguyên tắc SOLID của lập trình hướng đối tượng giúp làm cho các thiết kế hướng đối&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/solid-principles/">SOLID Principles</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Các nguyên tắc <strong>SOLID</strong> của lập trình hướng đối tượng giúp làm cho các thiết kế hướng đối tượng trở nên dễ hiểu, linh hoạt và dễ bảo trì hơn.</p>



<p class="wp-block-paragraph">Chúng cũng giúp dễ dàng tạo mã có thể đọc và kiểm tra được mà chúng ta có thể cùng nhau làm việc ở mọi nơi và mọi lúc cũng như giúp bạn biết cách viết mã tốt nhất</p>



<p class="wp-block-paragraph"><strong>SOLID</strong> là từ viết tắt đại diện cho năm nguyên tắc thiết kế của thiết kế lớp Hướng đối tượng. Những nguyên tắc này là:</p>



<ul class="wp-block-list">
<li><strong>S</strong>&nbsp;&#8211; Single-responsibility Principle</li>



<li><strong>O</strong>&nbsp;&#8211; Open-closed Principle</li>



<li><strong>L</strong>&nbsp;&#8211; Liskov Substitution Principle</li>



<li><strong>I</strong>&nbsp;&#8211; Interface Segregation Principle</li>



<li><strong>D</strong>&nbsp;&#8211; Dependency Inversion Principle</li>
</ul>



<p class="wp-block-paragraph">Mỗi nguyên tắc đóng vai trò là kim chỉ nam để thúc đẩy các phương pháp thiết kế tốt và giúp đảm bảo rằng mã có thể mở rộng, bảo trì và dễ hiểu. Trong bài viết này, chúng ta sẽ khám phá sâu từng nguyên tắc <strong>SOLID</strong> và cách chúng có thể được áp dụng cho <strong>Laravel</strong>.</p>



<h2 id="single-responsibility-principle" class="wp-block-heading"><strong>Single-responsibility Principle</strong></h2>



<p class="wp-block-paragraph">Nguyên tắc trách nhiệm duy nhất, hay <strong>SRP</strong>, tuyên bố rằng một lớp chỉ có một lý do để thay đổi. Nói cách khác, một lớp chỉ nên có một trách nhiệm và tập trung làm tốt một việc. Nguyên tắc này giúp giảm độ phức tạp của mã và giúp bảo trì dễ dàng hơn.</p>



<p class="wp-block-paragraph">Trong <strong>Laravel</strong>, <strong>SRP</strong> có thể được áp dụng bằng cách tạo các lớp nhỏ hơn, tập trung hơn để xử lý các tác vụ cụ thể. Ví dụ, thay vì có một lớp duy nhất xử lý đăng ký và đăng nhập của người dùng, sẽ tốt hơn nếu có các lớp riêng biệt để làm từng việc này.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="class User
{
	public function register($data) {
    // Register user logic
  }

  public function login($data) {
    // Login logic
  }
}
" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">User</span></span>
<span class="line"><span style="color: #F6F6F4">{</span></span>
<span class="line"><span style="color: #F6F6F4">	</span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">register</span><span style="color: #F6F6F4">($data) {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Register user logic</span></span>
<span class="line"><span style="color: #F6F6F4">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">login</span><span style="color: #F6F6F4">($data) {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Login logic</span></span>
<span class="line"><span style="color: #F6F6F4">  }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Thay vào đó, mỗi lớp sẽ có một nhiệm vụ riêng biệt.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="class UserRegistration {
  public function register($data) {
    // Register user logic
  }
}

class UserLogin {
  public function login($data) {
    // Login logic
  }
}
" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">UserRegistration</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">register</span><span style="color: #F6F6F4">($data) {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Register user logic</span></span>
<span class="line"><span style="color: #F6F6F4">  }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">UserLogin</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">login</span><span style="color: #F6F6F4">($data) {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Login logic</span></span>
<span class="line"><span style="color: #F6F6F4">  }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span></code></pre></div>



<h2 id="open-closed-principle-ocp" class="wp-block-heading"><strong>Open/Closed Principle (OCP)</strong></h2>



<p class="wp-block-paragraph">Nguyên tắc đóng mở có thể gây nhầm lẫn vì nó là nguyên tắc hai chiều. Theo định nghĩa của <strong><a href="https://www.freecodecamp.org/news/solid-principles-for-programming-and-software-design/#:~:text=principle.%20According%20to-,Bertrand%20Meyer%27s,-definition%20on%20Wikipedia">Bertrand Meyer</a></strong> trên <a href="https://www.freecodecamp.org/news/solid-principles-for-programming-and-software-design/#:~:text=Meyer%27s%20definition%20on-,Wikipedia,-%2C%20the%20open%2Dclosed">Wikipedia</a>, nguyên tắc đóng mở (<strong>OCP</strong>) nói rằng các thực thể phần mềm (lớp, mô-đun, chức năng, v.v.) phải mở để mở rộng nhưng đóng để sửa đổi.</p>



<p class="wp-block-paragraph">Định nghĩa này có thể gây nhầm lẫn, nhưng một ví dụ và sự làm rõ thêm sẽ giúp bạn hiểu rõ hơn.</p>



<p class="wp-block-paragraph">Có hai thuộc tính chính trong <strong>OCP</strong>:</p>



<ul class="wp-block-list">
<li>Nó có thể <strong>open</strong> &#8211; Điều này có nghĩa là bạn có thể mở rộng những gì mô-đun có thể thực hiện.</li>
</ul>



<ul class="wp-block-list">
<li>Nó <strong>closed</strong> để sửa đổi — Điều này có nghĩa là bạn không thể thay đổi mã nguồn, mặc dù bạn có thể mở rộng hoạt động của một mô-đun hoặc thực thể.</li>
</ul>



<p class="wp-block-paragraph"><strong>OCP</strong> có nghĩa là một lớp, mô-đun, hàm và các thực thể khác có thể mở rộng hành vi của chúng mà không cần sửa đổi mã nguồn. Nói cách khác, một thực thể có thể được mở rộng mà không cần sửa đổi chính thực thể đó. </p>



<p class="wp-block-paragraph">Trong <strong>Laravel</strong>, nguyên tắc này có thể được áp dụng bằng cách sử dụng các interface và các abstract class. Bằng cách xác định interface cho một tác vụ cụ thể, có thể tạo ra nhiều triển khai thực hiện tác vụ đó, mỗi tác vụ có chức năng riêng.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="class PaymentMethod {
  public function processPayment($amount) {
    // Payment processing logic
  }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">PaymentMethod</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">processPayment</span><span style="color: #F6F6F4">($amount) {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Payment processing logic</span></span>
<span class="line"><span style="color: #F6F6F4">  }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Thay vào đó:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="interface PaymentMethodInterface {
  public function processPayment($amount);
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">interface</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">PaymentMethodInterface</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">processPayment</span><span style="color: #F6F6F4">($amount);</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Chúng ta có thể implement để sử dụng và không ảnh hưởng gì đến mã nguồn:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="class CreditCardPayment implements PaymentMethodInterface {
  public function processPayment($amount) {
    // Credit card payment processing logic
  }
}

class BankTransferPayment implements PaymentMethodInterface {
  public function processPayment($amount) {
    // Bank transfer payment processing logic
  }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">CreditCardPayment</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">implements</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">PaymentMethodInterface</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">processPayment</span><span style="color: #F6F6F4">($amount) {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Credit card payment processing logic</span></span>
<span class="line"><span style="color: #F6F6F4">  }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">BankTransferPayment</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">implements</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">PaymentMethodInterface</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">processPayment</span><span style="color: #F6F6F4">($amount) {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Bank transfer payment processing logic</span></span>
<span class="line"><span style="color: #F6F6F4">  }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<h2 id="liskov-substitution-principle-lsp" class="wp-block-heading"><strong>Liskov Substitution Principle (LSP)</strong></h2>



<p class="wp-block-paragraph"><strong>LSP</strong> tuyên bố rằng các đối tượng của siêu lớp có thể được thay thế bằng các đối tượng của lớp con mà không ảnh hưởng đến tính chính xác của chương trình. Nói cách khác, một lớp con phải thay thế cho lớp cha của nó.</p>



<p class="wp-block-paragraph">Trong <strong>Laravel</strong>, nguyên tắc này có thể được áp dụng bằng cách sử dụng tính kế thừa và đa hình. Bằng cách tạo một lớp cơ sở xác định chức năng chung cho một tập hợp các lớp, có thể tạo các lớp con kế thừa từ lớp cơ sở và thêm chức năng độc đáo của riêng chúng.</p>



<p class="wp-block-paragraph">Một ví dụ rất phổ biến là kịch bản hình chữ nhật, hình vuông. Rõ ràng là tất cả các hình vuông đều là hình chữ nhật vì chúng là tứ giác có bốn góc đều là góc vuông. Nhưng không phải hình chữ nhật nào cũng là hình vuông. Để là hình vuông thì các cạnh của nó phải có cùng độ dài.</p>



<p class="wp-block-paragraph">Hãy ghi nhớ điều này, giả sử bạn có một lớp hình chữ nhật để tính diện tích hình chữ nhật và thực hiện các thao tác khác như set màu sắc cho nó</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="class Rectangle {
    public function setWidth($width)
		{
        $this-&gt;width = $width;
    }

    public function setHeight($height) 
		{
				$this-&gt;height = $height;
    }

    public function setColor($color)
		{
				// set color processing logic
    }

    public function getArea() 
		{
        return $this-&gt;width * $this-&gt;height;
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Rectangle</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">setWidth</span><span style="color: #F6F6F4">($width)</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">width </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $width;</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">setHeight</span><span style="color: #F6F6F4">($height) </span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">				</span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">height </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $height;</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">setColor</span><span style="color: #F6F6F4">($color)</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">				</span><span style="color: #7B7F8B">// set color processing logic</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">getArea</span><span style="color: #F6F6F4">() </span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">width </span><span style="color: #F286C4">*</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">height;</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Biết rõ rằng tất cả các hình vuông đều là hình chữ nhật, bạn có thể kế thừa các đặc tính của hình chữ nhật. Vì chiều rộng và chiều cao phải giống nhau nên bạn có thể điều chỉnh nó:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="class Square extends Rectangle {
    public function setWidth($width)
		{
        $this-&gt;width = $width;
        $this-&gt;height = $width;
    }
		public function setHeight($height)
		{
        $this-&gt;width = $height;
        $this-&gt;height = $height;
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Square</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">extends</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Rectangle</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">setWidth</span><span style="color: #F6F6F4">($width)</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">width </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $width;</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">height </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $width;</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">		</span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">setHeight</span><span style="color: #F6F6F4">($height)</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">width </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $height;</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">height </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $height;</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Nhìn vào ví dụ, nó sẽ hoạt động bình thường:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="$rectangle = new Rectangle();
$rectangle-&gt;setWidth(10);
$rectangle-&gt;setHeight(5);
$area = $rectangle-&gt;getArea());
echo $area; // 50" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">$rectangle </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">new</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Rectangle</span><span style="color: #F6F6F4">();</span></span>
<span class="line"><span style="color: #F6F6F4">$rectangle</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">setWidth</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">10</span><span style="color: #F6F6F4">);</span></span>
<span class="line"><span style="color: #F6F6F4">$rectangle</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">setHeight</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">5</span><span style="color: #F6F6F4">);</span></span>
<span class="line"><span style="color: #F6F6F4">$area </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $rectangle</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getArea</span><span style="color: #F6F6F4">());</span></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> $area; </span><span style="color: #7B7F8B">// 50</span></span></code></pre></div>



<p class="wp-block-paragraph">Ở phần trên, bạn sẽ nhận thấy rằng một hình chữ nhật được tạo và chiều rộng và chiều cao được đặt. Sau đó, bạn có thể tính toán diện tích chính xác.</p>



<p class="wp-block-paragraph">Nhưng theo <strong>LSP</strong>, bạn muốn các đối tượng của lớp con của bạn hoạt động giống như các đối tượng của lớp cha của bạn. Có nghĩa là nếu bạn thay thế Hình chữ nhật bằng Hình vuông, mọi thứ vẫn hoạt động tốt:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="$square = new Square();
$square-&gt;setWidth(10);
$square-&gt;setHeight(5);" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">$square </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">new</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Square</span><span style="color: #F6F6F4">();</span></span>
<span class="line"><span style="color: #F6F6F4">$square</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">setWidth</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">10</span><span style="color: #F6F6F4">);</span></span>
<span class="line"><span style="color: #F6F6F4">$square</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">setHeight</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">5</span><span style="color: #F6F6F4">);</span></span></code></pre></div>



<p class="wp-block-paragraph">Bạn sẽ nhận được 100, vì setWidth(10) được cho là đặt cả chiều rộng và chiều cao thành 10. Nhưng vì setHeight(5), giá trị này sẽ trả về 25.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="$square = new Square();
$square-&gt;setWidth(10);
$square-&gt;setHeight(5);
$area = $square-&gt;getArea());
echo $area; // 25" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">$square </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">new</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Square</span><span style="color: #F6F6F4">();</span></span>
<span class="line"><span style="color: #F6F6F4">$square</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">setWidth</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">10</span><span style="color: #F6F6F4">);</span></span>
<span class="line"><span style="color: #F6F6F4">$square</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">setHeight</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">5</span><span style="color: #F6F6F4">);</span></span>
<span class="line"><span style="color: #F6F6F4">$area </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $square</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getArea</span><span style="color: #F6F6F4">());</span></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> $area; </span><span style="color: #7B7F8B">// 25</span></span></code></pre></div>



<p class="wp-block-paragraph">Điều này phá vỡ <strong>LSP</strong>. Đối tượng hình vuông lớp con không thể thay thế đối tượng hình chữ nhật siêu lớp để tính diện tích. Để khắc phục điều này, cần có một lớp chung cho tất cả các hình dạng sẽ chứa tất cả các phương thức chung mà bạn muốn các đối tượng của lớp con của mình có quyền truy cập. Sau đó, đối với các phương thức riêng lẻ, bạn tạo một lớp riêng cho hình chữ nhật và hình vuông</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="class Shape {
    public function setColor($color)
		{
        $this-&gt;color = $color;
    }
    public function getColor()
		{
        return $this-&gt;color;
    }
}

class Rectangle extends Shape {
    public function setWidth($width)
		{
        $this-&gt;width = $width;
    }
    public function setHeight($height) {
        $this-&gt;height = $height;
    }
    public function getArea() {
        return $this-&gt;width * $this-&gt;height;
    }
}

class Square extends Shape {
    public function setSide($side) {
        $this-&gt;side = $side;
    }
    public function getArea() {
        return $this-&gt;side * $this-&gt;side;
    }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Shape</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">setColor</span><span style="color: #F6F6F4">($color)</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">color </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $color;</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">getColor</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">color;</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Rectangle</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">extends</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Shape</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">setWidth</span><span style="color: #F6F6F4">($width)</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">width </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $width;</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">setHeight</span><span style="color: #F6F6F4">($height) {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">height </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $height;</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">getArea</span><span style="color: #F6F6F4">() {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">width </span><span style="color: #F286C4">*</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">height;</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Square</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">extends</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Shape</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">setSide</span><span style="color: #F6F6F4">($side) {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">side </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $side;</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">getArea</span><span style="color: #F6F6F4">() {</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">side </span><span style="color: #F286C4">*</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">side;</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Bằng cách này, bạn có thể đặt màu và lấy màu bằng cách sử dụng siêu lớp hoặc lớp con:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="// superclass
$shape = new Shape();
$shape-&gt;setColor('red');
$color = $shape-&gt;getColor());
echo $color; // red

// subclass
$rectangle = new Rectangle();
$rectangle-&gt;setColor('green');
$rectangleColor = $rectangle-&gt;getColor());
echo $rectangleColor; // green

// subclass
$square = new Square();
$square-&gt;setColor('blue');
$squareColor = $square-&gt;getColor());
echo $squareColor; // blue" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #7B7F8B">// superclass</span></span>
<span class="line"><span style="color: #F6F6F4">$shape </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">new</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Shape</span><span style="color: #F6F6F4">();</span></span>
<span class="line"><span style="color: #F6F6F4">$shape</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">setColor</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">red</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">);</span></span>
<span class="line"><span style="color: #F6F6F4">$color </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $shape</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getColor</span><span style="color: #F6F6F4">());</span></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> $color; </span><span style="color: #7B7F8B">// red</span></span>
<span class="line"></span>
<span class="line"><span style="color: #7B7F8B">// subclass</span></span>
<span class="line"><span style="color: #F6F6F4">$rectangle </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">new</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Rectangle</span><span style="color: #F6F6F4">();</span></span>
<span class="line"><span style="color: #F6F6F4">$rectangle</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">setColor</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">green</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">);</span></span>
<span class="line"><span style="color: #F6F6F4">$rectangleColor </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $rectangle</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getColor</span><span style="color: #F6F6F4">());</span></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> $rectangleColor; </span><span style="color: #7B7F8B">// green</span></span>
<span class="line"></span>
<span class="line"><span style="color: #7B7F8B">// subclass</span></span>
<span class="line"><span style="color: #F6F6F4">$square </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">new</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Square</span><span style="color: #F6F6F4">();</span></span>
<span class="line"><span style="color: #F6F6F4">$square</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">setColor</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">blue</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">);</span></span>
<span class="line"><span style="color: #F6F6F4">$squareColor </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $square</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getColor</span><span style="color: #F6F6F4">());</span></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> $squareColor; </span><span style="color: #7B7F8B">// blue</span></span></code></pre></div>



<h2 id="interface-segregation-principle-isp" class="wp-block-heading"><strong>Interface Segregation Principle (ISP)</strong></h2>



<p class="wp-block-paragraph"><strong>ISP</strong> tuyên bố rằng các lớp không nên bị buộc phải triển khai các giao diện mà chúng không sử dụng. Nguyên tắc này giúp giảm độ phức tạp của mã và giúp bảo trì dễ dàng hơn.</p>



<p class="wp-block-paragraph">Trong <strong>Laravel</strong>, nguyên tắc này có thể được áp dụng bằng cách tạo các giao diện nhỏ hơn, tập trung hơn để xác định các nhiệm vụ cụ thể.</p>



<p class="wp-block-paragraph">Ví dụ: giả sử bạn có một giao diện xác định các phương thức để vẽ các hình dạng cụ thể.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="interface ShapeInterface {
    public function calculateArea();
    public function calculateVolume();
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">interface</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ShapeInterface</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateArea</span><span style="color: #F6F6F4">();</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateVolume</span><span style="color: #F6F6F4">();</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Khi bất kỳ lớp nào triển khai giao diện này, tất cả các phương thức phải được xác định ngay cả khi bạn không sử dụng chúng hoặc nếu chúng không áp dụng cho lớp đó.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="class Square implements ShapeInterface {
    public function calculateArea()
		{
        //...
    }
    public function calculateVolume()
		{
        //...
    }  
}

class Cuboid implements ShapeInterface {
    public function calculateArea()
		{
        //...
    }
    public function calculateVolume()
		{
        //...
    }    
}

class Rectangle implements ShapeInterface {
    public function calculateArea()
		{
        //...
    }
    public function calculateVolume()
		{
        //...
    }   
}
" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Square</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">implements</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ShapeInterface</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateArea</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #7B7F8B">//...</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateVolume</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #7B7F8B">//...</span></span>
<span class="line"><span style="color: #F6F6F4">    }  </span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Cuboid</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">implements</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ShapeInterface</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateArea</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #7B7F8B">//...</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateVolume</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #7B7F8B">//...</span></span>
<span class="line"><span style="color: #F6F6F4">    }    </span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Rectangle</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">implements</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ShapeInterface</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateArea</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #7B7F8B">//...</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateVolume</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #7B7F8B">//...</span></span>
<span class="line"><span style="color: #F6F6F4">    }   </span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Nhận thấy rằng chúng ta không thể tính thể tích của hình vuông hoặc hình chữ nhật. Vì lớp này triển khai giao diện nên bạn cần xác định tất cả các phương thức, ngay cả những phương thức bạn không sử dụng hoặc không cần.</p>



<p class="wp-block-paragraph">Thay vào đó, ta nên tách nhỏ interface ra:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="interface ShapeInterface {
    public function calculateArea();
}

interface ThreeDimensionalShapeInterface {
    public function calculateArea();
    public function calculateVolume();
}
" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">interface</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ShapeInterface</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateArea</span><span style="color: #F6F6F4">();</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">interface</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ThreeDimensionalShapeInterface</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateArea</span><span style="color: #F6F6F4">();</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateVolume</span><span style="color: #F6F6F4">();</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Bây giờ bạn có thể triển khai giao diện cụ thể hoạt động với từng lớp.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="class Square implements ShapeInterface {
    public function calculateArea()
		{
        //...
    } 
}

class Cuboid implements ThreeDimensionalShapeInterface {
    public function calculateArea()
		{
        //...
    }
    public function calculateVolume()
		{
        //...
    }    
}

class Rectangle implements ShapeInterface {
    public function calculateArea()
		{
        //...
    }  
}
" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Square</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">implements</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ShapeInterface</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateArea</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #7B7F8B">//...</span></span>
<span class="line"><span style="color: #F6F6F4">    } </span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Cuboid</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">implements</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ThreeDimensionalShapeInterface</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateArea</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #7B7F8B">//...</span></span>
<span class="line"><span style="color: #F6F6F4">    }</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateVolume</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #7B7F8B">//...</span></span>
<span class="line"><span style="color: #F6F6F4">    }    </span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Rectangle</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">implements</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">ShapeInterface</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">calculateArea</span><span style="color: #F6F6F4">()</span></span>
<span class="line"><span style="color: #F6F6F4">		{</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #7B7F8B">//...</span></span>
<span class="line"><span style="color: #F6F6F4">    }  </span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span></code></pre></div>



<h2 id="dependency-inversion-principle-dip" class="wp-block-heading"><strong>Dependency Inversion Principle (DIP)</strong></h2>



<p class="wp-block-paragraph"><strong>DIP</strong> nêu rõ rằng các mô-đun cấp cao không nên phụ thuộc vào các mô-đun cấp thấp, mà cả hai đều phải phụ thuộc vào sự trừu tượng hóa. Nguyên tắc này giúp giảm sự ghép nối giữa các mô-đun và giúp việc duy trì và mở rộng mã dễ dàng hơn.</p>



<p class="wp-block-paragraph">Theo <a href="https://en.wikipedia.org/wiki/Dependency_inversion_principle">Wikipedia</a>, nguyên tắc này nêu rõ rằng:</p>



<ul class="wp-block-list">
<li>Các mô-đun cấp cao không được nhập bất cứ thứ gì từ các mô-đun cấp thấp. Cả hai nên phụ thuộc vào sự trừu tượng (ví dụ: giao diện).</li>



<li>Sự trừu tượng phải độc lập với các chi tiết. Chi tiết (triển khai cụ thể) sẽ phụ thuộc vào sự trừu tượng.</li>
</ul>



<p class="wp-block-paragraph">Trong <strong>Laravel</strong>, nguyên tắc này có thể được áp dụng bằng cách sử dụng <strong>dependency injection</strong>. Bằng cách xác định các phần phụ thuộc dưới dạng trừu tượng thay vì triển khai cụ thể, có thể thay đổi cách triển khai phần phụ thuộc mà không ảnh hưởng đến mã phụ thuộc vào nó.</p>



<p class="wp-block-paragraph">Thay vì ta triển khai cụ thể:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="class UserController {
  public function showProfile(int|string $id) {
    $userRepository = new UserRepository;
    $user = $userRepository-&gt;getUser($id);

    return view('user.profile', ['user' =&gt; $user]);
  }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">UserController</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">showProfile</span><span style="color: #F6F6F4">(</span><span style="color: #F286C4">int</span><span style="color: #F6F6F4">|</span><span style="color: #F286C4">string</span><span style="color: #F6F6F4"> $id) {</span></span>
<span class="line"><span style="color: #F6F6F4">    $userRepository </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">new</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">UserRepository</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F6F6F4">    $user </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $userRepository</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getUser</span><span style="color: #F6F6F4">($id);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">view</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">user.profile</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">,</span><span style="color: #62E884"> </span><span style="color: #F6F6F4">[</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">user</span><span style="color: #DEE492">&#39;</span><span style="color: #62E884"> </span><span style="color: #F286C4">=&gt;</span><span style="color: #62E884"> </span><span style="color: #F6F6F4">$user]);</span></span>
<span class="line"><span style="color: #F6F6F4">  }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Thì ta có thể xác định phần phụ thuộc dưới dạng trừu tượng:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="class UserController {
  protected $userRepository;

  public function __construct(UserRepositoryInterface $userRepository) {
    $this-&gt;userRepository = $userRepository;
  }

  public function showProfile(int|string $id) {
    $user = $this-&gt;userRepository-&gt;getUser($id);

    return view('user.profile', ['user' =&gt; $user]);
  }
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">UserController</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">protected</span><span style="color: #F6F6F4"> $userRepository;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">__construct</span><span style="color: #F6F6F4">(</span><span style="color: #97E1F1; font-style: italic">UserRepositoryInterface</span><span style="color: #F6F6F4"> $userRepository) {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">userRepository </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> $userRepository;</span></span>
<span class="line"><span style="color: #F6F6F4">  }</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #F286C4">public</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">showProfile</span><span style="color: #F6F6F4">(</span><span style="color: #F286C4">int</span><span style="color: #F6F6F4">|</span><span style="color: #F286C4">string</span><span style="color: #F6F6F4"> $id) {</span></span>
<span class="line"><span style="color: #F6F6F4">    $user </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">userRepository</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getUser</span><span style="color: #F6F6F4">($id);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">return</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">view</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">user.profile</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">,</span><span style="color: #62E884"> </span><span style="color: #F6F6F4">[</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">user</span><span style="color: #DEE492">&#39;</span><span style="color: #62E884"> </span><span style="color: #F286C4">=&gt;</span><span style="color: #62E884"> </span><span style="color: #F6F6F4">$user]);</span></span>
<span class="line"><span style="color: #F6F6F4">  }</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<h2 id="advantages-of-solid" class="wp-block-heading">Advantages of SOLID</h2>



<p class="wp-block-paragraph">Sử dụng các nguyên tắc <strong>SOLID</strong> trong phát triển phần mềm có một số lợi ích:</p>



<ul class="wp-block-list">
<li><strong>Tăng khả năng bảo trì:</strong> Các nguyên tắc <strong>SOLID</strong> giúp tạo mã dễ bảo trì và sửa đổi hơn theo thời gian. Khi mỗi lớp hoặc mô-đun có một trách nhiệm duy nhất và tuân theo Nguyên tắc Mở/Đóng, các thay đổi có thể được thực hiện mà không ảnh hưởng đến các phần khác của mã.</li>



<li><strong>Tăng khả năng kiểm tra:</strong> Nguyên tắc <strong>SOLID</strong> cũng giúp kiểm tra mã dễ dàng hơn. Mã tuân theo Nguyên tắc trách nhiệm duy nhất thường dễ kiểm tra hơn vì có ít sự phụ thuộc hơn và ít tác dụng phụ có thể xảy ra hơn.</li>



<li><strong>Tăng tính linh hoạt:</strong> Bằng cách tuân thủ Nguyên tắc Mở/Đóng, bạn có thể tạo mã linh hoạt và có khả năng mở rộng hơn. Khi cần thêm chức năng mới, bạn có thể làm như vậy bằng cách thêm các lớp hoặc giao diện mới thay vì sửa đổi mã hiện có.</li>



<li><strong>Tổ chức mã tốt hơn:</strong> Bằng cách tuân theo các nguyên tắc <strong>SOLID</strong>, bạn có thể tổ chức mã của mình tốt hơn và làm cho các nhà phát triển khác dễ hiểu hơn. Mã được tổ chức tốt và tuân theo các mẫu thiết kế rõ ràng sẽ dễ bảo trì và mở rộng hơn.</li>
</ul>



<h2 id="conclusion" class="wp-block-heading">Conclusion</h2>



<p class="wp-block-paragraph"><strong>SOLID</strong> là một tập hợp các nguyên tắc thiết kế giúp thúc đẩy các phương pháp thiết kế tốt và đảm bảo rằng mã có thể mở rộng, bảo trì và dễ hiểu. Bằng cách áp dụng những nguyên tắc này trong Laravel, các nhà phát triển có thể tạo mã mạnh mẽ, có thể bảo trì và dễ mở rộng quy mô.</p>



<p class="wp-block-paragraph">Cảm ơn mọi người đã dành thời gian để đọc 🙏</p>
<p>The post <a href="https://blog.tomosia.com.vn/solid-principles/">SOLID Principles</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/solid-principles/feed/</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
			</item>
		<item>
		<title>[AWS SDK for PHP] Xử lý upload multiple files đồng thời lên S3 Storage hiệu quả</title>
		<link>https://blog.tomosia.com.vn/aws-sdk-for-php-xu-ly-upload-multiple-files-dong-thoi-len-s3-storage-hieu-qua/</link>
					<comments>https://blog.tomosia.com.vn/aws-sdk-for-php-xu-ly-upload-multiple-files-dong-thoi-len-s3-storage-hieu-qua/#comments</comments>
		
		<dc:creator><![CDATA[admin_tomosia]]></dc:creator>
		<pubDate>Fri, 01 Dec 2023 04:17:57 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[s3]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=2125</guid>

					<description><![CDATA[<p>Việc lưu trữ và quản lý file trên đám mây đã trở thành một phần quan trọng trong&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/aws-sdk-for-php-xu-ly-upload-multiple-files-dong-thoi-len-s3-storage-hieu-qua/">[AWS SDK for PHP] Xử lý upload multiple files đồng thời lên S3 Storage hiệu quả</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Việc lưu trữ và quản lý file trên đám mây đã trở thành một phần quan trọng trong quá trình phát triển ứng dụng. Việc upload nhiều files đồng thời không chỉ giúp tiết kiệm thời gian mà còn tối ưu hiệu suất, đặc biệt quan trọng đối với các ứng dụng yêu cầu xử lý lượng lớn dữ liệu.</p>



<p class="wp-block-paragraph"> Giả sử chúng ta có 1000 files cần upload lên S3 Storage. </p>



<p class="wp-block-paragraph">Thông thường, chúng ta sẽ làm như sau: </p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="foreach ($uploadFiles as $uploadFile) {
    $response = $this-&gt;s3StorageClient-&gt;putObject([
        'Bucket'       =&gt; ****,
        'Key'          =&gt; $uploadFile['filename'],
        'SourceFile'   =&gt; $uploadFile['content'],
        'ACL'          =&gt; 'public-read'
//        ....
   ]);
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F286C4">foreach</span><span style="color: #F6F6F4"> ($uploadFiles </span><span style="color: #F286C4">as</span><span style="color: #F6F6F4"> $uploadFile) {</span></span>
<span class="line"><span style="color: #F6F6F4">    $response </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">s3StorageClient</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">putObject</span><span style="color: #F6F6F4">([</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">Bucket</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">       </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">****</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">Key</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">          </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> $uploadFile[</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">filename</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">],</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">SourceFile</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">   </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> $uploadFile[</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">content</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">],</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">ACL</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">          </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">public-read</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #7B7F8B">//        ....</span></span>
<span class="line"><span style="color: #F6F6F4">   ]);</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Theo cách trên, nếu chúng ta upload 10 files thì sẽ mất 10 lần để xử lý putObject, nếu upload 1000 files thì sẽ lần lượt xử lý putObject 1000 lần.</p>



<p class="wp-block-paragraph">Để giải quyết việc này, AWS PHP SDK có cung cấp một class CommandPool, class này có thể thực thi nhiều lệnh AWS cùng lúc.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="$commands = [];
foreach ($uploadFiles as $uploadFile) {
    $commands[] = $this-&gt;s3StorageClient-&gt;getCommand('PutObject', [
        'Bucket'       =&gt; ****,
        'Key'          =&gt; $uploadFile['filename'],
        'SourceFile'   =&gt; $uploadFile['content'],
        'ACL'          =&gt; 'public-read'
    ]);
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">$commands </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> [];</span></span>
<span class="line"><span style="color: #F286C4">foreach</span><span style="color: #F6F6F4"> ($uploadFiles </span><span style="color: #F286C4">as</span><span style="color: #F6F6F4"> $uploadFile) {</span></span>
<span class="line"><span style="color: #F6F6F4">    $commands[] </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">s3StorageClient</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getCommand</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">PutObject</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">, [</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">Bucket</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">       </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">****</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">Key</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">          </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> $uploadFile[</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">filename</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">],</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">SourceFile</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">   </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> $uploadFile[</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">content</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">],</span></span>
<span class="line"><span style="color: #F6F6F4">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">ACL</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">          </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">public-read</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #F6F6F4">    ]);</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Đầu tiên, không thực thi lệnh putObject trong vòng lặp mà hãy sử dụng <strong>getCommand</strong> để tạo lệnh cho <strong>putObject</strong> và lưu trữ nó trong một mảng.</p>



<p class="wp-block-paragraph">Sau đó, bạn có thể dễ dàng thực thi các lệnh đồng thời bằng cách đưa s3 instance và mảng commands được vào phương thức <strong>CommandPool::batch.</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="CommandPool::batch($this-&gt;s3StorageClient, $commands);" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #97E1F1; font-style: italic">CommandPool</span><span style="color: #F286C4">::</span><span style="color: #62E884">batch</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">s3StorageClient, $commands);</span></span></code></pre></div>



<p class="wp-block-paragraph">Ở đây chúng ta có thể lấy files đồng thời sau khi gọi hàm <strong>CommandPool::batch</strong></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">PHP</span><span role="button" tabindex="0" data-code="$responses = CommandPool::batch($this-&gt;s3StorageClient, $commands);

foreach ($responses as $response) {
  // code here
}" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">$responses </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">CommandPool</span><span style="color: #F286C4">::</span><span style="color: #62E884">batch</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE; font-style: italic">$this</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">s3StorageClient, $commands);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F286C4">foreach</span><span style="color: #F6F6F4"> ($responses </span><span style="color: #F286C4">as</span><span style="color: #F6F6F4"> $response) {</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #7B7F8B">// code here</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Em cũng đã triển khai cách trên áp dụng vào dự án và cũng khá hiệu quả về performance.</p>



<p class="wp-block-paragraph">Đối với những bài toán upload số lượng files lên đến hàng trăm nghìn, hàng triệu, chúng ta có thể zip từng nhóm files rồi thực hiện upload đồng thời theo cách trên, nhưng cần sử dụng thêm một service để giải nén file zip sau khi upload (AWS Lambda chẳng hạn).</p>



<p class="wp-block-paragraph"><br><strong>Tài liệu tham khảo: </strong></p>



<ul class="wp-block-list">
<li><a href="https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_commands.html#command-pool">https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_commands.html#command-pool</a></li>



<li><a href="https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.CommandPool.html">https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.CommandPool.html</a></li>
</ul>
<p>The post <a href="https://blog.tomosia.com.vn/aws-sdk-for-php-xu-ly-upload-multiple-files-dong-thoi-len-s3-storage-hieu-qua/">[AWS SDK for PHP] Xử lý upload multiple files đồng thời lên S3 Storage hiệu quả</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/aws-sdk-for-php-xu-ly-upload-multiple-files-dong-thoi-len-s3-storage-hieu-qua/feed/</wfw:commentRss>
			<slash:comments>8</slash:comments>
		
		
			</item>
		<item>
		<title>Alpine.js là gì ?  Hãy Cùng tìm hiểu về cách sử dụng nào</title>
		<link>https://blog.tomosia.com.vn/alpine-js-la-gi-hay-cung-tim-hieu-ve-cach-su-dung-nao/</link>
					<comments>https://blog.tomosia.com.vn/alpine-js-la-gi-hay-cung-tim-hieu-ve-cach-su-dung-nao/#comments</comments>
		
		<dc:creator><![CDATA[quivo]]></dc:creator>
		<pubDate>Fri, 01 Dec 2023 02:35:52 +0000</pubDate>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Alpine]]></category>
		<category><![CDATA[Laravel]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=1701</guid>

					<description><![CDATA[<p>Alpine.js là gì ? Alpine.js là một JavaScript framework nhẹ và dễ sử dụng, giúp bạn tạo ra&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/alpine-js-la-gi-hay-cung-tim-hieu-ve-cach-su-dung-nao/">Alpine.js là gì ?  Hãy Cùng tìm hiểu về cách sử dụng nào</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h3 id="alpine-js-la-gi" class="wp-block-heading">Alpine.js là gì ?</h3>



<p class="wp-block-paragraph">Alpine.js là một JavaScript framework nhẹ và dễ sử dụng, giúp bạn tạo ra các tương tác trực tiếp trên giao diện người dùng (UI) một cách dễ dàng và nhanh chóng mà không cần phải chạy npm, biên dịch tập lệnh, định cấu hình webpack. Nó là một giải pháp thay thế đơn giản và hiệu quả cho các frontend framework khác như Vue, React &amp; Angular. Hãy nghĩ về nó giống như&nbsp;<a href="https://tailwindcss.com/?ref=blog.tomosia.com.vn" target="_blank" rel="noreferrer noopener"><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-vivid-cyan-blue-color">Tailwind</mark></a>&nbsp;dành cho JavaScript.</p>



<p class="wp-block-paragraph"></p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="563" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/11/social-1024x563.jpeg" alt="" class="wp-image-1704" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/11/social-1024x563.jpeg 1024w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/social-300x165.jpeg 300w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/social-768x422.jpeg 768w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/social-380x209.jpeg 380w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/social-800x440.jpeg 800w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/social-1160x638.jpeg 1160w, https://blog.tomosia.com.vn/wp-content/uploads/2023/11/social.jpeg 1200w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h3 id="cach-su-dung" class="wp-block-heading">Cách sử dụng</h3>



<p class="wp-block-paragraph">Theo&nbsp;&nbsp;<a rel="noreferrer noopener" href="https://github.com/alpinejs/alpine?ref=blog.tomosia.com.vn" target="_blank">tài liệu của Alpine.js</a>&nbsp;, cú pháp của nó gần như được mượn hoàn toàn từ&nbsp;&nbsp;<a rel="noreferrer noopener" href="https://vuejs.org/?ref=blog.tomosia.com.vn" target="_blank">Vue.js</a>&nbsp;&nbsp;(và phần mở rộng&nbsp;&nbsp;<a rel="noreferrer noopener" href="https://angularjs.org/?ref=blog.tomosia.com.vn" target="_blank">Angular.js</a>&nbsp;), vì vậy nếu bạn đã biết một trong hai framework này thì bạn sẽ không phải mất nhiều thời gian để bắt đầu.</p>



<p class="wp-block-paragraph">Trong blog này, Chúng ta sẽ tìm hiểu cách sử dụng Alpine.js trong Laravel với hai ví dụ.</p>



<ol class="wp-block-list">
<li>Alpine.js CDN</li>



<li>Laravel Mix</li>
</ol>



<h4 id="su-dung-qua-cdn" class="wp-block-heading">Sử dụng qua CDN</h4>



<p class="wp-block-paragraph">Bạn chỉ cần thêm một thẻ script liên kết thư viện (xem ví dụ bên dưới). Rất đơn giản phải không nào! Bạn không cần phải biên dịch javascript hoặc cấu trúc dự án của mình theo bất kỳ cách cụ thể nào.</p>



<div class="wp-block-kevinbatdorf-code-block-pro alignfull cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:8.4296875px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">JavaScript</span><span role="button" tabindex="0" data-code="&lt;html&gt;
&lt;head&gt;
    &lt;script defer src=&quot;https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js&quot;&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1 x-data=&quot;{ message: 'I ❤️ Alpine' }&quot; x-text=&quot;message&quot;&gt;&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">&lt;</span><span style="color: #F286C4">html</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">&lt;</span><span style="color: #F286C4">head</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">    &lt;</span><span style="color: #F286C4">script</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">defer</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">src</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">&gt;&lt;/</span><span style="color: #F286C4">script</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">&lt;/</span><span style="color: #F286C4">head</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">&lt;</span><span style="color: #F286C4">body</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">    &lt;</span><span style="color: #F286C4">h1</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">x-data</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">{ message: &#39;I ❤️ Alpine&#39; }</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">x-text</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">message</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">&gt;&lt;/</span><span style="color: #F286C4">h1</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">&lt;/</span><span style="color: #F286C4">body</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">&lt;/</span><span style="color: #F286C4">html</span><span style="color: #F6F6F4">&gt;</span></span></code></pre></div>



<h4 id="su-dung-qua-laravel-mix" class="wp-block-heading">Sử dụng qua Laravel mix</h4>



<p class="wp-block-paragraph">Trước tiên, bạn cần cài đặt Alpine js bằng lệnh npm bên dưới:</p>



<pre class="wp-block-code"><code>npm install alpinejs</code></pre>



<p class="wp-block-paragraph">Tiếp đó, bạn cần import vào <code><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-black-color"><strong>resources/js/app.js</strong></mark></code> file</p>



<pre class="wp-block-code"><code>import 'alpinejs';</code></pre>



<p class="wp-block-paragraph">Cuối cùng chỉ cần chạy lệnh</p>



<pre class="wp-block-code"><code>npm run dev</code></pre>



<p class="wp-block-paragraph">Bây giờ, bạn có thể sử dụng được alpine (nhớ thêm <strong>app.js</strong> vào blade view nhé)</p>



<pre class="wp-block-code"><code>&lt;script src="{{ mix('js/app.js') }}"&gt;&lt;/script&gt;</code></pre>



<p class="wp-block-paragraph">Cùng xem 1 ví dụ đơn giản nhé:</p>



<div class="wp-block-kevinbatdorf-code-block-pro alignfull cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#f6f6f4;--cbp-line-number-width:16.859375px;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#333545;color:#ebebe6">JavaScript</span><span role="button" tabindex="0" data-code="&lt;div 
    x-data=&quot;{ show: false }&quot; 
    x-show=&quot;show&quot; 
    x-on:notify.window=&quot;() =&gt; { show = true; setTimeout(() =&gt; { show = false; }, 5000 ) }&quot;
    style=&quot;display:none;&quot;
    class=&quot;toast active&quot;
&gt;
    &lt;div class=&quot;toast-content&quot;&gt;
        &lt;i class=&quot;ti ti-check toast-icon&quot; x-on:click=&quot;show = false&quot;&gt;&lt;/i&gt;
        &lt;div class=&quot;message&quot;&gt;
            &lt;span class=&quot;message-title&quot;&gt;Ví dụ&lt;/span&gt;
            &lt;span class=&quot;message-content&quot;&gt;Ví dụ về alpine js&lt;/span&gt;
            &lt;span x-on:click=&quot;show = false&quot; class=&quot;close&quot;&gt;
                &lt;i class=&quot;ti ti-x&quot;&gt;&lt;/i&gt;
            &lt;/span&gt;
        &lt;/div&gt;
        &lt;div class=&quot;progress active&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;" style="color:#f6f6f4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula-soft" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F6F6F4">&lt;</span><span style="color: #F286C4">div</span><span style="color: #F6F6F4"> </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #62E884; font-style: italic">x-data</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">{ show: false }</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4"> </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #62E884; font-style: italic">x-show</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">show</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4"> </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #EE6666; font-style: italic; text-decoration: underline">x-on:notify.window=&quot;()</span><span style="color: #F6F6F4"> </span><span style="color: #EE6666; font-style: italic; text-decoration: underline">=&gt;</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">{</span><span style="color: #F6F6F4"> show </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">true</span><span style="color: #F6F6F4">; </span><span style="color: #62E884">setTimeout</span><span style="color: #F6F6F4">(() </span><span style="color: #F286C4">=&gt;</span><span style="color: #F6F6F4"> { show </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">false</span><span style="color: #F6F6F4">; }, </span><span style="color: #BF9EEE">5000</span><span style="color: #F6F6F4"> ) </span><span style="color: #F286C4">}</span><span style="color: #DEE492">&quot;</span></span>
<span class="line"><span style="color: #E7EE98">    style=</span><span style="color: #DEE492">&quot;</span><span style="color: #EE6666; font-style: italic; text-decoration: underline">display:none;&quot;</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #62E884; font-style: italic">class</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">toast active</span><span style="color: #DEE492">&quot;</span></span>
<span class="line"><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">    &lt;</span><span style="color: #F286C4">div</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">class</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">toast-content</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">        &lt;</span><span style="color: #F286C4">i</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">class</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">ti ti-check toast-icon</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">x-on</span><span style="color: #F286C4">:</span><span style="color: #62E884; font-style: italic">click</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">show = false</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">&gt;&lt;/</span><span style="color: #F286C4">i</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">        &lt;</span><span style="color: #F286C4">div</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">class</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">message</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">            &lt;</span><span style="color: #F286C4">span</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">class</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">message-title</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">&gt;Ví dụ&lt;/</span><span style="color: #F286C4">span</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">            &lt;</span><span style="color: #F286C4">span</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">class</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">message-content</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">&gt;Ví dụ về alpine js&lt;/</span><span style="color: #F286C4">span</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">            &lt;</span><span style="color: #F286C4">span</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">x-on</span><span style="color: #F286C4">:</span><span style="color: #62E884; font-style: italic">click</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">show = false</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">class</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">close</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">                &lt;</span><span style="color: #F286C4">i</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">class</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">ti ti-x</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">&gt;&lt;/</span><span style="color: #F286C4">i</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">            &lt;/</span><span style="color: #F286C4">span</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">        &lt;/</span><span style="color: #F286C4">div</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">        &lt;</span><span style="color: #F286C4">div</span><span style="color: #F6F6F4"> </span><span style="color: #62E884; font-style: italic">class</span><span style="color: #F286C4">=</span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">progress active</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">&gt;&lt;/</span><span style="color: #F286C4">div</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">    &lt;/</span><span style="color: #F286C4">div</span><span style="color: #F6F6F4">&gt;</span></span>
<span class="line"><span style="color: #F6F6F4">&lt;/</span><span style="color: #F286C4">div</span><span style="color: #F6F6F4">&gt;</span></span></code></pre></div>



<p class="wp-block-paragraph">Ở ví dụ trên, tôi có một component alert được phản ứng khi sự kiện <strong>notify</strong> được thực hiện thì sẽ hiển thị thông báo.</p>



<h3 id="ket-luan" class="wp-block-heading">Kết luận</h3>



<p class="wp-block-paragraph">Với sự đơn giản và gọn nhẹ của Alpine, tôi tin rằng đây sẽ là 1 trong số các giải pháp tốt nhất cho bạn trong một số trường hợp thay vì sử dụng các Js framework khác  như Vue hay React để rồi nhận thêm sự cồng kềnh, phức tạp mà chúng mang lại.</p>



<p class="wp-block-paragraph">Hiện tại, cùng với sự kết hợp với Tailwind, Livewire và Laravel, bộ tứ này đã và đang hình thành nên 1 ngăn xếp công nghệ mới được gọi là ngăn xếp TALL. Nếu tò mò bạn có thể xem tại <a rel="noreferrer noopener" href="https://blog.laravelvietnam.org/tall-stack/" data-type="link" data-id="https://blog.laravelvietnam.org/tall-stack/" target="_blank">blog.laravelvietnam</a>.</p>
<p>The post <a href="https://blog.tomosia.com.vn/alpine-js-la-gi-hay-cung-tim-hieu-ve-cach-su-dung-nao/">Alpine.js là gì ?  Hãy Cùng tìm hiểu về cách sử dụng nào</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/alpine-js-la-gi-hay-cung-tim-hieu-ve-cach-su-dung-nao/feed/</wfw:commentRss>
			<slash:comments>24</slash:comments>
		
		
			</item>
		<item>
		<title>Vẽ biểu đồ với Mermaid</title>
		<link>https://blog.tomosia.com.vn/ve-bieu-do-voi-mermaid/</link>
					<comments>https://blog.tomosia.com.vn/ve-bieu-do-voi-mermaid/#comments</comments>
		
		<dc:creator><![CDATA[admin_tomosia]]></dc:creator>
		<pubDate>Wed, 04 Oct 2023 03:47:15 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Chưa phân loại]]></category>
		<category><![CDATA[Diagram]]></category>
		<category><![CDATA[UML]]></category>
		<category><![CDATA[Laravel]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=271</guid>

					<description><![CDATA[<p>Chúng ta thường dùng các công cụ để vẽ biểu đồ như Draw.io, Cacoo&#8230; Sau khi biết đến&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/ve-bieu-do-voi-mermaid/">Vẽ biểu đồ với Mermaid</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Chúng ta thường dùng các công cụ để vẽ biểu đồ như Draw.io, Cacoo&#8230; Sau khi biết đến  Mermaid mình đã không còn dùng các công cụ trên nữa.</p>



<p class="wp-block-paragraph"><a href="https://mermaid.js.org/">Mermaid</a> là một thư viện JavaScript cho phép bạn tạo các biểu đồ cực kì dễ dàng, bằng cú pháp đơn giản dựa trên Markdown. Nó hỗ trợ hầu hết các loại biểu đồ: biểu đồ trình tự, biểu đồ lớp, biểu đồ trạng thái, ERD&#8230; Các biểu đồ được tạo bằng cách khai báo mã và văn bản, sau đó được xuất thành biểu đồ, có thể dễ dàng tích hợp biểu đồ vào Github.</p>



<h2 class="wp-block-heading" id="khai-niem-automation-test-la-gi"><span id="sequence-diagrams">Sequence diagrams</span></h2>



<p class="wp-block-paragraph">Giờ chúng ta sẽ vẽ thử 1 <a href="https://mermaid.js.org/syntax/sequenceDiagram.html" data-type="link" data-id="https://mermaid.js.org/syntax/sequenceDiagram.html">sequence diagram </a>với mermaid. </p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="sequenceDiagram
    Alice-&gt;&gt;John: Hello John, how are you?
    John--&gt;&gt;Alice: Great!
    Alice-)John: See you later!" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2">sequenceDiagram</span></span>
<span class="line"><span style="color: #F8F8F2">    Alice</span><span style="color: #FF79C6">-&gt;&gt;</span><span style="color: #F8F8F2">John: Hello John, how are you</span><span style="color: #FF79C6">?</span></span>
<span class="line"><span style="color: #F8F8F2">    John</span><span style="color: #FF79C6">--&gt;&gt;</span><span style="color: #F8F8F2">Alice</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> Great</span><span style="color: #FF79C6">!</span></span>
<span class="line"><span style="color: #F8F8F2">    Alice</span><span style="color: #FF79C6">-</span><span style="color: #F8F8F2">)John: See you later</span><span style="color: #FF79C6">!</span></span></code></pre></div>



<p class="wp-block-paragraph">Chỉ cần khai báo như trên mermaid sẽ tự generate ra một biểu đồ luồng</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="675" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/10/sequence-1024x675.png" alt="" class="wp-image-367" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/10/sequence-1024x675.png 1024w, https://blog.tomosia.com.vn/wp-content/uploads/2023/10/sequence-300x198.png 300w, https://blog.tomosia.com.vn/wp-content/uploads/2023/10/sequence-768x506.png 768w, https://blog.tomosia.com.vn/wp-content/uploads/2023/10/sequence-380x250.png 380w, https://blog.tomosia.com.vn/wp-content/uploads/2023/10/sequence-800x527.png 800w, https://blog.tomosia.com.vn/wp-content/uploads/2023/10/sequence.png 1032w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2 id="class-diagrams" class="wp-block-heading">Class diagrams</h2>



<p class="wp-block-paragraph">Vẽ thử một class diagram</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="classDiagram
class BankAccount{
    +String owner
    +BigDecimal balance
    +deposit(amount)
    +withdrawal(amount)
}" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2">classDiagram</span></span>
<span class="line"><span style="color: #FF79C6">class</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD">BankAccount</span><span style="color: #F8F8F2">{</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #FF79C6">+</span><span style="color: #F8F8F2">String owner</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #FF79C6">+</span><span style="color: #F8F8F2">BigDecimal balance</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #FF79C6">+</span><span style="color: #50FA7B">deposit</span><span style="color: #F8F8F2">(</span><span style="color: #FFB86C; font-style: italic">amount</span><span style="color: #F8F8F2">)</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #FF79C6">+</span><span style="color: #50FA7B">withdrawal</span><span style="color: #F8F8F2">(</span><span style="color: #FFB86C; font-style: italic">amount</span><span style="color: #F8F8F2">)</span></span>
<span class="line"><span style="color: #F8F8F2">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Output chúng ta nhận được</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="574" height="394" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/10/class_diagram.png" alt="" class="wp-image-373" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/10/class_diagram.png 574w, https://blog.tomosia.com.vn/wp-content/uploads/2023/10/class_diagram-300x206.png 300w, https://blog.tomosia.com.vn/wp-content/uploads/2023/10/class_diagram-380x261.png 380w" sizes="auto, (max-width: 574px) 100vw, 574px" /></figure>



<h2 id="entity-relationship-diagram" class="wp-block-heading">Entity Relationship Diagram</h2>



<p class="wp-block-paragraph">Vẽ một biểu đồ ERD đơn giản, chúng ta có thể khai báo được các trường, kiểu dữ liệu, quan hệ giữa các bảng cực kì đơn giản.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="erDiagram
    CUSTOMER ||--o{ ORDER : places
    CUSTOMER {
        string name
        string custNumber
        string sector
    }
    ORDER {
        int orderNumber
        string deliveryAddress
    }" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2">erDiagram</span></span>
<span class="line"><span style="color: #F8F8F2">    CUSTOMER </span><span style="color: #FF79C6">||--</span><span style="color: #F8F8F2">o{ ORDER : places</span></span>
<span class="line"><span style="color: #F8F8F2">    CUSTOMER {</span></span>
<span class="line"><span style="color: #F8F8F2">        string name</span></span>
<span class="line"><span style="color: #F8F8F2">        string custNumber</span></span>
<span class="line"><span style="color: #F8F8F2">        string sector</span></span>
<span class="line"><span style="color: #F8F8F2">    }</span></span>
<span class="line"><span style="color: #F8F8F2">    ORDER {</span></span>
<span class="line"><span style="color: #F8F8F2">        int orderNumber</span></span>
<span class="line"><span style="color: #F8F8F2">        string deliveryAddress</span></span>
<span class="line"><span style="color: #F8F8F2">    }</span></span></code></pre></div>



<p class="wp-block-paragraph">Output chúng ta nhận được</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="532" height="792" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/10/Screenshot-2023-10-04-at-10.21.57.png" alt="" class="wp-image-378" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/10/Screenshot-2023-10-04-at-10.21.57.png 532w, https://blog.tomosia.com.vn/wp-content/uploads/2023/10/Screenshot-2023-10-04-at-10.21.57-202x300.png 202w, https://blog.tomosia.com.vn/wp-content/uploads/2023/10/Screenshot-2023-10-04-at-10.21.57-380x566.png 380w" sizes="auto, (max-width: 532px) 100vw, 532px" /></figure>



<h2 class="wp-block-heading" id="state-diagrams"><span id="state-diagram">State diagram<a href="https://mermaid.js.org/syntax/stateDiagram.html#state-diagrams">​</a></span></h2>



<p class="wp-block-paragraph">Vẽ biểu đồ trạng thái</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="stateDiagram-v2
    [*] --&gt; Still
    Still --&gt; [*]

    Still --&gt; Moving
    Moving --&gt; Still
    Moving --&gt; Crash
    Crash --&gt; [*]" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2">stateDiagram</span><span style="color: #FF79C6">-</span><span style="color: #F8F8F2">v2</span></span>
<span class="line"><span style="color: #F8F8F2">    [</span><span style="color: #FF79C6">*</span><span style="color: #F8F8F2">] </span><span style="color: #FF79C6">--&gt;</span><span style="color: #F8F8F2"> Still</span></span>
<span class="line"><span style="color: #F8F8F2">    Still </span><span style="color: #FF79C6">--&gt;</span><span style="color: #F8F8F2"> [</span><span style="color: #FF79C6">*</span><span style="color: #F8F8F2">]</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F8F8F2">    Still </span><span style="color: #FF79C6">--&gt;</span><span style="color: #F8F8F2"> Moving</span></span>
<span class="line"><span style="color: #F8F8F2">    Moving </span><span style="color: #FF79C6">--&gt;</span><span style="color: #F8F8F2"> Still</span></span>
<span class="line"><span style="color: #F8F8F2">    Moving </span><span style="color: #FF79C6">--&gt;</span><span style="color: #F8F8F2"> Crash</span></span>
<span class="line"><span style="color: #F8F8F2">    Crash </span><span style="color: #FF79C6">--&gt;</span><span style="color: #F8F8F2"> [</span><span style="color: #FF79C6">*</span><span style="color: #F8F8F2">]</span></span></code></pre></div>



<p class="wp-block-paragraph">Output nhận được</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="634" height="876" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/10/Screenshot-2023-10-04-at-10.32.13.png" alt="" class="wp-image-383" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/10/Screenshot-2023-10-04-at-10.32.13.png 634w, https://blog.tomosia.com.vn/wp-content/uploads/2023/10/Screenshot-2023-10-04-at-10.32.13-217x300.png 217w, https://blog.tomosia.com.vn/wp-content/uploads/2023/10/Screenshot-2023-10-04-at-10.32.13-380x525.png 380w" sizes="auto, (max-width: 634px) 100vw, 634px" /></figure>



<p class="wp-block-paragraph">Chúng ta đã tìm hiểu xong 4 loại biểu đồ hay dùng nhất với dev. Ngoài ra Mermaid cũng support rất nhiều loại biểu đồ khác mọi người có thể vào <a href="https://mermaid.js.org/intro/" data-type="link" data-id="https://mermaid.js.org/intro/">mermaid document</a> để tìm hiểu thêm. Document của họ viết rất rõ ràng và có demo cụ thể hết rồi.</p>



<h2 id="tong-ket" class="wp-block-heading">Tổng kết</h2>



<p class="wp-block-paragraph">Mermaid sẽ giúp chúng ta định nghĩa các biểu đồ cho dự án cực kì dễ ràng, quản lý và hiển thị được các biểu đồ trên github. Nó là công cụ cực kì hữu ích giúp định nghĩa các thiết kế cho dự  án. Thanks for reading&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/ve-bieu-do-voi-mermaid/">Vẽ biểu đồ với Mermaid</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/ve-bieu-do-voi-mermaid/feed/</wfw:commentRss>
			<slash:comments>34</slash:comments>
		
		
			</item>
		<item>
		<title>20 Laravel Eloquent Tips and Tricks (P1)</title>
		<link>https://blog.tomosia.com.vn/20-laravel-eloquent-tips-and-tricks-p1/</link>
					<comments>https://blog.tomosia.com.vn/20-laravel-eloquent-tips-and-tricks-p1/#comments</comments>
		
		<dc:creator><![CDATA[admin_tomosia]]></dc:creator>
		<pubDate>Mon, 02 Oct 2023 03:33:23 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[Tricks]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Eloquent]]></category>
		<category><![CDATA[Laravel]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=205</guid>

					<description><![CDATA[<p>Eloquent ORM được sủ dụng rất nhiều trong 1 project Laravel, tuy nhiên để sử dụng được tối đa những gì Laravel cung cấp thì không phải ai cũng biết. Trong bài viết này mình sẽ chỉ cho các bạn một vài thủ thuật, hi vọng sẽ giúp ích cho các bạn trong một vài trường hợp cụ thể.</p>
<p>The post <a href="https://blog.tomosia.com.vn/20-laravel-eloquent-tips-and-tricks-p1/">20 Laravel Eloquent Tips and Tricks (P1)</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Eloquent ORM được sủ dụng rất nhiều trong 1 project Laravel, tuy nhiên để sử dụng được tối đa những gì Laravel cung cấp thì không phải ai cũng biết. Trong bài viết này mình sẽ chỉ cho các bạn một vài thủ thuật, hi vọng sẽ giúp ích cho các bạn trong một vài trường hợp cụ thể.</p>



<h2 id="1-increments-va-decrements" class="wp-block-heading">1. Increments và Decrements</h2>



<p class="wp-block-paragraph">Khi muốn update tăng 1 đơn vị cho 1 column thay vì viết như này.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="$post = Post::find($postId);
$post-&gt;view_count++;
$post-&gt;save();" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2">$post </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD; font-style: italic">Post</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">find</span><span style="color: #F8F8F2">($postId);</span></span>
<span class="line"><span style="color: #F8F8F2">$post</span><span style="color: #FF79C6">-&gt;</span><span style="color: #F8F8F2">view_count</span><span style="color: #FF79C6">++</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #F8F8F2">$post</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">save</span><span style="color: #F8F8F2">();</span></span></code></pre></div>



<p class="wp-block-paragraph">Bạn có thể viết lại như này</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="$post = Post::find($postId);
$post-&gt;increment('view_count');" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2">$post </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD; font-style: italic">Post</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">find</span><span style="color: #F8F8F2">($postId);</span></span>
<span class="line"><span style="color: #F8F8F2">$post</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">increment</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">view_count</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">);</span></span></code></pre></div>



<p class="wp-block-paragraph">Hoặc</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="Post::find($postId)-&gt;increment('view_count');
Post::find($postId)-&gt;increment('view_count', 10); // +10
Product::find($productId)-&gt;decrement('stock'); // -1" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #8BE9FD; font-style: italic">Post</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">find</span><span style="color: #F8F8F2">($postId)</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">increment</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">view_count</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">);</span></span>
<span class="line"><span style="color: #8BE9FD; font-style: italic">Post</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">find</span><span style="color: #F8F8F2">($postId)</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">increment</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">view_count</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">, </span><span style="color: #BD93F9">10</span><span style="color: #F8F8F2">); </span><span style="color: #6272A4">// +10</span></span>
<span class="line"><span style="color: #8BE9FD; font-style: italic">Product</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">find</span><span style="color: #F8F8F2">($productId)</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">decrement</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">stock</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">); </span><span style="color: #6272A4">// -1</span></span></code></pre></div>



<h2 id="2-xory-methods" class="wp-block-heading">2. XorY methods</h2>



<p class="wp-block-paragraph">Laravel Eloquent có khả nhiều function kết hợp 2 methods kiểu như &#8220;hãy làm X trước nếu không thì làm Y&#8221;</p>



<ul class="wp-block-list">
<li><strong>findOrFail</strong></li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="$user = User::find($id);
if (!$user) {
   abort(404);
}" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2">$user </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD; font-style: italic">User</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">find</span><span style="color: #F8F8F2">($id);</span></span>
<span class="line"><span style="color: #FF79C6">if</span><span style="color: #F8F8F2"> (</span><span style="color: #FF79C6">!</span><span style="color: #F8F8F2">$user) {</span></span>
<span class="line"><span style="color: #F8F8F2">   </span><span style="color: #50FA7B">abort</span><span style="color: #F8F8F2">(</span><span style="color: #BD93F9">404</span><span style="color: #F8F8F2">);</span></span>
<span class="line"><span style="color: #F8F8F2">}</span></span></code></pre></div>



<p class="wp-block-paragraph">↓</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="$user = User::findOrFail($id);" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2">$user </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD; font-style: italic">User</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">findOrFail</span><span style="color: #F8F8F2">($id);</span></span></code></pre></div>



<ul class="wp-block-list">
<li><strong>firstOrCreate</strong></li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="$user = User::where('email', $email)-&gt;first();
  if (!$user) {
  User::create([
  'email' =&gt; $email
  ]);
}" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2">$user </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD; font-style: italic">User</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">where</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">email</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">, $email)</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">first</span><span style="color: #F8F8F2">();</span></span>
<span class="line"><span style="color: #F8F8F2">  </span><span style="color: #FF79C6">if</span><span style="color: #F8F8F2"> (</span><span style="color: #FF79C6">!</span><span style="color: #F8F8F2">$user) {</span></span>
<span class="line"><span style="color: #F8F8F2">  </span><span style="color: #8BE9FD; font-style: italic">User</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">create</span><span style="color: #F8F8F2">([</span></span>
<span class="line"><span style="color: #F8F8F2">  </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">email</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">=&gt;</span><span style="color: #F8F8F2"> $email</span></span>
<span class="line"><span style="color: #F8F8F2">  ]);</span></span>
<span class="line"><span style="color: #F8F8F2">}</span></span></code></pre></div>



<p class="wp-block-paragraph">↓</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="$user = User::firstOrCreate(['email' =&gt; $email]);" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2">$user </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD; font-style: italic">User</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">firstOrCreate</span><span style="color: #F8F8F2">([</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">email</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">=&gt;</span><span style="color: #F8F8F2"> $email]);</span></span></code></pre></div>



<h2 id="3-model-boot-method" class="wp-block-heading">3. Model boot() method</h2>



<p class="wp-block-paragraph">Trong Laravel Eloquent có một function&nbsp;<code>boot()</code>&nbsp;cho phép bạn ghi đè lại các giá trị mặc định.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="class User extends Model
{
    /**
    * @return void
    */
    public static function boot(): void
    {
        parent::boot();
        static::updating(function($model)
        {
            // do some logging
            // thay thế một số property, ví dụ $model-&gt;something = transform($something);
        });
    }
}" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #FF79C6">class</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD">User</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">extends</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD; font-style: italic">Model</span></span>
<span class="line"><span style="color: #F8F8F2">{</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #6272A4">/**</span></span>
<span class="line"><span style="color: #6272A4">    * </span><span style="color: #FF79C6">@return</span><span style="color: #6272A4"> </span><span style="color: #FF79C6">void</span></span>
<span class="line"><span style="color: #6272A4">    */</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #FF79C6">public</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">static</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">function</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">boot</span><span style="color: #F8F8F2">()</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">void</span></span>
<span class="line"><span style="color: #F8F8F2">    {</span></span>
<span class="line"><span style="color: #F8F8F2">        </span><span style="color: #8BE9FD; font-style: italic">parent</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">boot</span><span style="color: #F8F8F2">();</span></span>
<span class="line"><span style="color: #F8F8F2">        </span><span style="color: #8BE9FD; font-style: italic">static</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">updating</span><span style="color: #F8F8F2">(</span><span style="color: #FF79C6">function</span><span style="color: #F8F8F2">($model)</span></span>
<span class="line"><span style="color: #F8F8F2">        {</span></span>
<span class="line"><span style="color: #F8F8F2">            </span><span style="color: #6272A4">// do some logging</span></span>
<span class="line"><span style="color: #F8F8F2">            </span><span style="color: #6272A4">// thay thế một số property, ví dụ $model-&gt;something = transform($something);</span></span>
<span class="line"><span style="color: #F8F8F2">        });</span></span>
<span class="line"><span style="color: #F8F8F2">    }</span></span>
<span class="line"><span style="color: #F8F8F2">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Ứng dụng nhiều nhất của function này là set uuid cho đối tượng</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="/**
* @return void
*/
public static function boot(): void
{
    parent::boot();
    self::creating(function ($model) {
        $model-&gt;uuid = (string)Uuid::generate();
    });
}" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #6272A4">/**</span></span>
<span class="line"><span style="color: #6272A4">* </span><span style="color: #FF79C6">@return</span><span style="color: #6272A4"> </span><span style="color: #FF79C6">void</span></span>
<span class="line"><span style="color: #6272A4">*/</span></span>
<span class="line"><span style="color: #FF79C6">public</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">static</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">function</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">boot</span><span style="color: #F8F8F2">()</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">void</span></span>
<span class="line"><span style="color: #F8F8F2">{</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #8BE9FD; font-style: italic">parent</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">boot</span><span style="color: #F8F8F2">();</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #8BE9FD; font-style: italic">self</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">creating</span><span style="color: #F8F8F2">(</span><span style="color: #FF79C6">function</span><span style="color: #F8F8F2"> ($model) {</span></span>
<span class="line"><span style="color: #F8F8F2">        $model</span><span style="color: #FF79C6">-&gt;</span><span style="color: #F8F8F2">uuid </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> (</span><span style="color: #8BE9FD; font-style: italic">string</span><span style="color: #F8F8F2">)</span><span style="color: #8BE9FD; font-style: italic">Uuid</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">generate</span><span style="color: #F8F8F2">();</span></span>
<span class="line"><span style="color: #F8F8F2">    });</span></span>
<span class="line"><span style="color: #F8F8F2">}</span></span></code></pre></div>



<p class="wp-block-paragraph"></p>



<h2 id="4-them-dieu-kien-hoac-ordering-trong-relationship" class="wp-block-heading">4. Thêm điều kiện hoặc ordering trong relationship</h2>



<p class="wp-block-paragraph">Dưới đây là một cách mà các bạn thường dùng để định nghĩa một relationship</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="/**
* @return mixed
*/
public function users()
{
    return $this-&gt;hasMany('App\User');    
}" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #6272A4">/**</span></span>
<span class="line"><span style="color: #6272A4">* </span><span style="color: #FF79C6">@return</span><span style="color: #6272A4"> </span><span style="color: #FF79C6">mixed</span></span>
<span class="line"><span style="color: #6272A4">*/</span></span>
<span class="line"><span style="color: #FF79C6">public</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">function</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">users</span><span style="color: #F8F8F2">()</span></span>
<span class="line"><span style="color: #F8F8F2">{</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #FF79C6">return</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9; font-style: italic">$this</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">hasMany</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">App\User</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">);    </span></span>
<span class="line"><span style="color: #F8F8F2">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Tuy nhiên bạn hoàn toàn có thể thêm&nbsp;<code>where</code>&nbsp;hoặc&nbsp;<code>orderBy</code></p>



<p class="wp-block-paragraph">Ví dụ trong trường hợp cụ thể, bạn cần tạo quan hệ giữa bảng&nbsp;<code>categories</code>&nbsp;và&nbsp;<code>posts</code>&nbsp;nhưng thêm điều kiện là&nbsp;<code>post</code>&nbsp;phải có trạng thái là&nbsp;<code>APPROVED</code>&nbsp;và sắp xếp theo thứ tụ tăng dần.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="/**
* @return mixed
*/
public function posts() 
{
    return $this-&gt;hasMany('App\Models\Category')-&gt;where('status', 'APPROVED')-&gt;orderBy('id', 'DESC');
}" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #6272A4">/**</span></span>
<span class="line"><span style="color: #6272A4">* </span><span style="color: #FF79C6">@return</span><span style="color: #6272A4"> </span><span style="color: #FF79C6">mixed</span></span>
<span class="line"><span style="color: #6272A4">*/</span></span>
<span class="line"><span style="color: #FF79C6">public</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">function</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">posts</span><span style="color: #F8F8F2">() </span></span>
<span class="line"><span style="color: #F8F8F2">{</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #FF79C6">return</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9; font-style: italic">$this</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">hasMany</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">App\Models\Category</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">)</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">where</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">status</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">, </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">APPROVED</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">)</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">orderBy</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">id</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">, </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">DESC</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">);</span></span>
<span class="line"><span style="color: #F8F8F2">}</span></span></code></pre></div>



<h2 id="5-model-properties-timestamps-appends" class="wp-block-heading">5. Model properties: timestamps, appends, &#8230;</h2>



<p class="wp-block-paragraph">Có một vài parameters của Eloquent Model, được thể hiện dưới dạng properties của class đó. Một số cái phổ biến nhất có thể là:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="class User extends Model {
    protected $table = 'users';
    protected $fillable = ['email', 'password']; // Những fileds có thể được set giá trị bằng cách dùng User::create()
    protected $dates = ['created_at', 'deleted_at']; // Những fields sẽ được set bởi Carbon-ized
    protected $appends = ['field1', 'field2']; // Các giá trị bổ sung được trả về trong JSON 
}" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #FF79C6">class</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD">User</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">extends</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD; font-style: italic">Model</span><span style="color: #F8F8F2"> {</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #FF79C6">protected</span><span style="color: #F8F8F2"> $table </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">users</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #FF79C6">protected</span><span style="color: #F8F8F2"> $fillable </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> [</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">email</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">, </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">password</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">]; </span><span style="color: #6272A4">// Những fileds có thể được set giá trị bằng cách dùng User::create()</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #FF79C6">protected</span><span style="color: #F8F8F2"> $dates </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> [</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">created_at</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">, </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">deleted_at</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">]; </span><span style="color: #6272A4">// Những fields sẽ được set bởi Carbon-ized</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #FF79C6">protected</span><span style="color: #F8F8F2"> $appends </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> [</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">field1</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">, </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">field2</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">]; </span><span style="color: #6272A4">// Các giá trị bổ sung được trả về trong JSON </span></span>
<span class="line"><span style="color: #F8F8F2">}</span></span></code></pre></div>



<p class="wp-block-paragraph">Khoannnnnnnnnnnnnnnnnnn, Còn nữa&#8230;</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="protected $primaryKey = 'uuid'; // Primary key k phải lúc nào cũng bắt buộc phải là id
public $incrementing = false; // và thậm chí k cần phải tự động tăng luông 
protected $perPage = 25; // Bạn có thể override số lượng data trong 1 page khi sủ dụng pagination, giá trị này default là 15
const CREATED_AT = 'created_at';
const UPDATED_AT = 'updated_at'; // Thay đổi được tên column created_at và updated_at luôn nè 
public $timestamps = false; // Hoặc khai báo là k cần sủ dụng chúng
protected $dateFormat = 'U'; //Hoặc bạn có thể thay đổi kiểu dữ liệu của chúng. Ví dụ chuyển created_at và updated_at sang integer thì làm như ví dụ này." style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M16.5 8.25V6a2.25 2.25 0 00-2.25-2.25H6A2.25 2.25 0 003.75 6v8.25A2.25 2.25 0 006 16.5h2.25m8.25-8.25H18a2.25 2.25 0 012.25 2.25V18A2.25 2.25 0 0118 20.25h-7.5A2.25 2.25 0 018.25 18v-1.5m8.25-8.25h-6a2.25 2.25 0 00-2.25 2.25v6"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #FF79C6">protected</span><span style="color: #F8F8F2"> $primaryKey </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">uuid</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">; </span><span style="color: #6272A4">// Primary key k phải lúc nào cũng bắt buộc phải là id</span></span>
<span class="line"><span style="color: #FF79C6">public</span><span style="color: #F8F8F2"> $incrementing </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">false</span><span style="color: #F8F8F2">; </span><span style="color: #6272A4">// và thậm chí k cần phải tự động tăng luông </span></span>
<span class="line"><span style="color: #FF79C6">protected</span><span style="color: #F8F8F2"> $perPage </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">25</span><span style="color: #F8F8F2">; </span><span style="color: #6272A4">// Bạn có thể override số lượng data trong 1 page khi sủ dụng pagination, giá trị này default là 15</span></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">CREATED_AT</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">created_at</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #FF79C6">const</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">UPDATED_AT</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">updated_at</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">; </span><span style="color: #6272A4">// Thay đổi được tên column created_at và updated_at luôn nè </span></span>
<span class="line"><span style="color: #FF79C6">public</span><span style="color: #F8F8F2"> $timestamps </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #BD93F9">false</span><span style="color: #F8F8F2">; </span><span style="color: #6272A4">// Hoặc khai báo là k cần sủ dụng chúng</span></span>
<span class="line"><span style="color: #FF79C6">protected</span><span style="color: #F8F8F2"> $dateFormat </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">U</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">; </span><span style="color: #6272A4">//Hoặc bạn có thể thay đổi kiểu dữ liệu của chúng. Ví dụ chuyển created_at và updated_at sang integer thì làm như ví dụ này.</span></span></code></pre></div>



<p class="wp-block-paragraph">Và tất nhiên là còn nhiều hơn nữa, trên đây mình đã liệt kê những cái thú vị nhất, để biết thêm chi tiết, vui lòng kiểm tra ở&nbsp;<code>abstract Model Class</code></p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">To be continued&#8230;</p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://blog.tomosia.com.vn/20-laravel-eloquent-tips-and-tricks-p1/">20 Laravel Eloquent Tips and Tricks (P1)</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/20-laravel-eloquent-tips-and-tricks-p1/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
			</item>
		<item>
		<title>Những cập nhật trong Laravel 10</title>
		<link>https://blog.tomosia.com.vn/nhung-cap-nhat-trong-laravel-10/</link>
					<comments>https://blog.tomosia.com.vn/nhung-cap-nhat-trong-laravel-10/#comments</comments>
		
		<dc:creator><![CDATA[Việt Nguyễn]]></dc:creator>
		<pubDate>Wed, 27 Sep 2023 09:03:14 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Laravel]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=56</guid>

					<description><![CDATA[<p>Sau hơn một thập kỷ kể từ khi giới thiệu vào tháng Sáu năm 2011,&#160;Framework Laravel&#160;đã trở nên&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/nhung-cap-nhat-trong-laravel-10/">Những cập nhật trong Laravel 10</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Sau hơn một thập kỷ kể từ khi giới thiệu vào tháng Sáu năm 2011,&nbsp;<strong>Framework Laravel</strong>&nbsp;đã trở nên cực kỳ phổ biến. Các phiên bản của Laravel được release hằng năm với những nâng cấp đáng kể.</p>



<p class="wp-block-paragraph">Mới đây, vào ngày 14 tháng 2 năm 2023, phiên bản&nbsp;<strong>Laravel 10</strong>&nbsp;chính thức được phát hành. Chúng ta hãy cùng nhau tìm hiểu xem phiên bản này có những thay đổi và cập nhật gì so với những phiên bản trước nhé.</p>



<h2 id="native-type-declarations" class="wp-block-heading">Native Type Declarations</h2>



<p class="wp-block-paragraph">Trước version 10: sử dụng&nbsp;<strong>DocBlocks</strong>&nbsp;để làm rõ chức năng của một function và loại parameters hoặc response mong đợi.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="    /**
    * Determine whether the user can create models.
    *
    * @param User $user
    * @return IlluminateAuthAccessResponse|bool
    */
    public function create(User $user)
    {
      //
    }" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2">    </span><span style="color: #6272A4">/**</span></span>
<span class="line"><span style="color: #6272A4">    * Determine whether the user can create models.</span></span>
<span class="line"><span style="color: #6272A4">    *</span></span>
<span class="line"><span style="color: #6272A4">    * </span><span style="color: #FF79C6">@param</span><span style="color: #6272A4"> </span><span style="color: #8BE9FD; font-style: italic">User</span><span style="color: #6272A4"> $user</span></span>
<span class="line"><span style="color: #6272A4">    * </span><span style="color: #FF79C6">@return</span><span style="color: #6272A4"> </span><span style="color: #8BE9FD; font-style: italic">IlluminateAuthAccessResponse</span><span style="color: #6272A4">|</span><span style="color: #FF79C6">bool</span></span>
<span class="line"><span style="color: #6272A4">    */</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #FF79C6">public</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">function</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">create</span><span style="color: #F8F8F2">(</span><span style="color: #8BE9FD; font-style: italic">User</span><span style="color: #F8F8F2"> $user)</span></span>
<span class="line"><span style="color: #F8F8F2">    {</span></span>
<span class="line"><span style="color: #F8F8F2">      </span><span style="color: #6272A4">//</span></span>
<span class="line"><span style="color: #F8F8F2">    }</span></span></code></pre></div>



<p class="wp-block-paragraph">Version 10:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request): View
    {
        return view('');
    }
" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #F8F8F2">    </span><span style="color: #6272A4">/**</span></span>
<span class="line"><span style="color: #6272A4">     * Store a newly created resource in storage.</span></span>
<span class="line"><span style="color: #6272A4">     */</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #FF79C6">public</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">function</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">store</span><span style="color: #F8F8F2">(</span><span style="color: #8BE9FD; font-style: italic">Request</span><span style="color: #F8F8F2"> $request)</span><span style="color: #FF79C6">:</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD; font-style: italic">View</span></span>
<span class="line"><span style="color: #F8F8F2">    {</span></span>
<span class="line"><span style="color: #F8F8F2">        </span><span style="color: #FF79C6">return</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">view</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;&#39;</span><span style="color: #F8F8F2">);</span></span>
<span class="line"><span style="color: #F8F8F2">    }</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Để đảm bảo được sự tương thích ngược của framework (breaking changes), các thuộc tính sẽ được áp dụng cho:</p>



<ul class="wp-block-list">
<li>Dữ liệu trả về (return types)</li>



<li>Tham số của phương thức (method arguments)</li>



<li>Loại bỏ một số khai báo types không còn cần thiết ở docblock</li>



<li>Cho phép có thể khai báo ngay trong các tham số của closure</li>
</ul>



<h2 id="ho-tro-sua-cot-cho-csdl" class="wp-block-heading">Hỗ trợ sửa cột cho CSDL</h2>



<p class="wp-block-paragraph">Nhằm loại bỏ dần nhu cầu sử dụng package&nbsp;<strong>doctrine/dbal</strong>, một tính năng mới đã được giới thiệu trong Laravel 10 cho phép các nhà phát triển sử dụng phương thức&nbsp;<strong>change()</strong>&nbsp;để sửa đổi các cột mà không cần các gói bổ sung.</p>



<p class="wp-block-paragraph">Sử dụng phương thức change() để chỉnh sửa cột.</p>



<p class="wp-block-paragraph">Ví dụ: Để sửa kiểu dữ liệu từ&nbsp;<strong>integer</strong>&nbsp;-&gt;&nbsp;<strong>bigInt</strong>&nbsp;ta làm như sau</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# before
$table-&gt;integer('user_balance')-&gt;unsigned()-&gt;default(0)-&gt;comment('balance');

# after
$table-&gt;bigInteger('user_balance')-&gt;unsigned()-&gt;default(0)-&gt;comment('balance')-&gt;change();
" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #6272A4"># before</span></span>
<span class="line"><span style="color: #F8F8F2">$table</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">integer</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">user_balance</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">)</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">unsigned</span><span style="color: #F8F8F2">()</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">default</span><span style="color: #F8F8F2">(</span><span style="color: #BD93F9">0</span><span style="color: #F8F8F2">)</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">comment</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">balance</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">);</span></span>
<span class="line"></span>
<span class="line"><span style="color: #6272A4"># after</span></span>
<span class="line"><span style="color: #F8F8F2">$table</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">bigInteger</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">user_balance</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">)</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">unsigned</span><span style="color: #F8F8F2">()</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">default</span><span style="color: #F8F8F2">(</span><span style="color: #BD93F9">0</span><span style="color: #F8F8F2">)</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">comment</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">balance</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">)</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">change</span><span style="color: #F8F8F2">();</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Note:</p>



<ul class="wp-block-list">
<li>Cần thêm tất cả thuộc tính của cột khi thay đổi nếu không chúng sẽ bị loại bỏ.</li>



<li>Nếu đã cài đặt&nbsp;<strong>doctrine/dbal</strong>, nên khai báo phương thức&nbsp;<strong>Schema::useNativeSchemaOperationsIfPossible()</strong>&nbsp;trong <strong>App/Providers/AppServiceProvider</strong>&nbsp;để sử dụng tính năng này. Laravel sẽ ưu tiên nó trước khi sử dụng đến package và không hỗ trợ cho&nbsp;<strong>SQLite</strong>.</li>
</ul>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="use IlluminateSupportFacadesSchema;
class AppServiceProvider extends ServiceProvider
{
  public function boot()
  {
    Schema::useNativeSchemaOperationsIfPossible();
  }
}
" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #FF79C6">use</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD; font-style: italic">IlluminateSupportFacadesSchema</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #FF79C6">class</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD">AppServiceProvider</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">extends</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD; font-style: italic">ServiceProvider</span></span>
<span class="line"><span style="color: #F8F8F2">{</span></span>
<span class="line"><span style="color: #F8F8F2">  </span><span style="color: #FF79C6">public</span><span style="color: #F8F8F2"> </span><span style="color: #FF79C6">function</span><span style="color: #F8F8F2"> </span><span style="color: #50FA7B">boot</span><span style="color: #F8F8F2">()</span></span>
<span class="line"><span style="color: #F8F8F2">  {</span></span>
<span class="line"><span style="color: #F8F8F2">    </span><span style="color: #8BE9FD; font-style: italic">Schema</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">useNativeSchemaOperationsIfPossible</span><span style="color: #F8F8F2">();</span></span>
<span class="line"><span style="color: #F8F8F2">  }</span></span>
<span class="line"><span style="color: #F8F8F2">}</span></span>
<span class="line"></span></code></pre></div>



<h2 id="process-interaction" class="wp-block-heading">Process Interaction</h2>



<p class="wp-block-paragraph"><strong>Process Interaction</strong>&nbsp;giúp việc thử nghiệm và chạy các quy trình&nbsp;<strong>CLI</strong>&nbsp;trở nên dễ dàng.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#282A36"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="use IlluminateSupportFacadesProcess;
$result = Process::run('ls -la');
$result-&gt;successful();
$result-&gt;failed();
$result-&gt;exitCode();
$result-&gt;output();
$result-&gt;errorOutput();
$result-&gt;throw();
$result-&gt;throwIf(condition);
" style="color:#F8F8F2;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dracula" style="background-color: #282A36" tabindex="0"><code><span class="line"><span style="color: #FF79C6">use</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD; font-style: italic">IlluminateSupportFacadesProcess</span><span style="color: #F8F8F2">;</span></span>
<span class="line"><span style="color: #F8F8F2">$result </span><span style="color: #FF79C6">=</span><span style="color: #F8F8F2"> </span><span style="color: #8BE9FD; font-style: italic">Process</span><span style="color: #FF79C6">::</span><span style="color: #50FA7B">run</span><span style="color: #F8F8F2">(</span><span style="color: #E9F284">&#39;</span><span style="color: #F1FA8C">ls -la</span><span style="color: #E9F284">&#39;</span><span style="color: #F8F8F2">);</span></span>
<span class="line"><span style="color: #F8F8F2">$result</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">successful</span><span style="color: #F8F8F2">();</span></span>
<span class="line"><span style="color: #F8F8F2">$result</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">failed</span><span style="color: #F8F8F2">();</span></span>
<span class="line"><span style="color: #F8F8F2">$result</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">exitCode</span><span style="color: #F8F8F2">();</span></span>
<span class="line"><span style="color: #F8F8F2">$result</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">output</span><span style="color: #F8F8F2">();</span></span>
<span class="line"><span style="color: #F8F8F2">$result</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">errorOutput</span><span style="color: #F8F8F2">();</span></span>
<span class="line"><span style="color: #F8F8F2">$result</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">throw</span><span style="color: #F8F8F2">();</span></span>
<span class="line"><span style="color: #F8F8F2">$result</span><span style="color: #FF79C6">-&gt;</span><span style="color: #50FA7B">throwIf</span><span style="color: #F8F8F2">(</span><span style="color: #BD93F9">condition</span><span style="color: #F8F8F2">);</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Process Interaction giúp chúng ta:</p>



<ul class="wp-block-list">
<li>Xử lý đầu ra của&nbsp;<strong>process</strong>&nbsp;khi nhận được</li>



<li>Thiết lập&nbsp;<strong>Process</strong>&nbsp;không đồng bộ</li>



<li>Tạo ra nhóm các&nbsp;<strong>process</strong></li>



<li>Các tính năng testing phong phú thông qua&nbsp;<strong>fake</strong>()</li>



<li>Ngăn chặn ngoại lệ trong quá trình testing</li>
</ul>



<p class="wp-block-paragraph">Process là một tính năng mới rất được đầu tư với nhiều phương thức và option được cung cấp. Bạn có thể tìm hiểu chi tiết ở&nbsp;<a rel="noreferrer noopener" href="https://laravel.com/docs/10.x/processes" target="_blank">docs về phần này của Laravel</a></p>



<h2 id="cung-cap-1-package-moi-laravel-pennant" class="wp-block-heading">Cung cấp 1 package mới &#8211; Laravel Pennant</h2>



<p class="wp-block-paragraph">Laravel Pennant cung cấp một cách tiếp cận gọn nhẹ, được sắp xếp hợp lý để quản lý các cờ tính năng của ứng dụng của bạn.</p>



<p class="wp-block-paragraph">Nó cho phép chúng ra tự tin triển khai dần dần các tính năng ứng dụng mới, thử nghiệm các thiết kế giao diện mới.</p>



<p class="wp-block-paragraph">Bạn có thể tìm hiểu chi tiết nó trong&nbsp;<a href="https://laravel.com/docs/10.x/pennant#main-content" target="_blank" rel="noreferrer noopener">docs của Laravel 10</a>.</p>
<p>The post <a href="https://blog.tomosia.com.vn/nhung-cap-nhat-trong-laravel-10/">Những cập nhật trong Laravel 10</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/nhung-cap-nhat-trong-laravel-10/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
	</channel>
</rss>
