<?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>php Archives - Tomoshare</title>
	<atom:link href="https://blog.tomosia.com.vn/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.tomosia.com.vn/tag/php/</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=6.9.4</generator>

<image>
	<url>https://blog.tomosia.com.vn/wp-content/uploads/2023/09/cropped-icon-32x32.png</url>
	<title>php Archives - Tomoshare</title>
	<link>https://blog.tomosia.com.vn/tag/php/</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/#respond</comments>
		
		<dc:creator><![CDATA[hoa nguyen]]></dc:creator>
		<pubDate>Thu, 25 Dec 2025 09:26:41 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[cronjob]]></category>
		<category><![CDATA[Scheduler]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[php]]></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>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>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><strong>Tư duy</strong>: Scheduler là &#8220;orchestrator&#8221;, không phải &#8220;executor&#8221;.</p>



<p>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>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><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><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><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>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>Ở 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><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>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><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><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><strong>Ví dụ</strong>:</p>



<p>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>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>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><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><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><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><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>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>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>Đây là điểm phân biệt hệ &#8220;chạy được&#8221; và hệ &#8220;chạy đúng&#8221;.</p>



<p><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><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><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><strong>Ví dụ — Pattern batch timestamp</strong>:</p>



<p>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><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>Job sẽ nhận&nbsp;<code>scheduledAt</code>&nbsp;từ scheduler event và dùng để query đúng time window.</p>



<p><strong>Ví dụ với sub-minute scheduling trong Laravel 12</strong>:</p>



<p>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><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>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><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><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><strong>Lưu ý</strong>: Trong scheduler, bạn có thể chỉ định queue khi schedule job:</p>



<p>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>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>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><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><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><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>Scheduler fail nguy hiểm vì nó&nbsp;<strong>âm thầm</strong>.</p>



<p><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><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><strong>Ví dụ — Scheduler hooks trong Laravel 12</strong>:</p>



<p>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><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><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>Ở môi trường deploy liên tục, scheduler/worker cần &#8220;graceful&#8221;:</p>



<p><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><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><strong>Ví dụ — Laravel 12&nbsp;<code>onOneServer()</code></strong>:</p>



<p>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><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>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><strong>Best practice — Laravel 12</strong>: Tách helper functions theo domain để dễ maintain:</p>



<p>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>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><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><strong>Schedule Groups — Laravel 12</strong>:</p>



<p>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><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><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><strong>Ví dụ — Laravel 12 timezone</strong>:</p>



<p>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><strong>Cách 1: Set timezone trong config (khuyến nghị)</strong>:</p>



<p>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>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><strong>Cách 2: Set timezone cho từng task riêng</strong>:</p>



<p>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><strong>Lưu ý quan trọng về DST (Daylight Saving Time)</strong>:</p>



<p>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><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>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><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>0</slash:comments>
		
		
			</item>
		<item>
		<title>Hướng dẫn kết nối Laravel + MongoDB</title>
		<link>https://blog.tomosia.com.vn/huong-dan-ket-noi-laravel-mongodb/</link>
					<comments>https://blog.tomosia.com.vn/huong-dan-ket-noi-laravel-mongodb/#comments</comments>
		
		<dc:creator><![CDATA[Ninh nguyen]]></dc:creator>
		<pubDate>Fri, 12 Jan 2024 06:12:18 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[php]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=3065</guid>

					<description><![CDATA[<p>1. Khái niệm MongoDB MongoDB là một database hướng tài liệu (document), một dạng NoSQL database. Vì thế, MongoDB&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/huong-dan-ket-noi-laravel-mongodb/">Hướng dẫn kết nối Laravel + MongoDB</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 id="1-khai-niem-mongodb" class="wp-block-heading"><strong>1. Khái niệm MongoDB</strong></h2>



<p><strong>MongoDB</strong> là một database hướng tài liệu (document), một dạng NoSQL database. Vì thế, MongoDB sẽ tránh cấu trúc table-based của relational database để thích ứng với các tài liệu như JSON có một schema rất linh hoạt gọi là BSON. Sử dụng lưu trữ dữ liệu dưới dạng Document JSON nên mỗi một collection sẽ các các kích cỡ và các document khác nhau. Các dữ liệu được lưu trữ trong document kiểu JSON nên truy vấn sẽ rất nhanh.</p>



<h2 id="2-khi-nao-su-dung-mongodb" class="wp-block-heading"><strong>2. Khi nào sử dụng MongoDB</strong></h2>



<p><strong>Quản lý và truyền tải content</strong>&nbsp;– Quản lý đa dạng nhiều product của content chỉ trong một kho lưu trữ data cho phép thay đổi và phản hồi nhanh chóng mà không chịu thêm phức tạp thêm từ hệ thống content.</p>



<p><strong>Cấu trúc Mobile và Social</strong>&nbsp;– MongoDB cung cấp một platform có sẵn, phản xạ nhanh, và dễ mở rộng cho phép rất nhiều khả năng đột phá, phân tích real-time, và hỗ trợ toàn cầu.</p>



<p><strong>Quản lý data khách hàng</strong>&nbsp;– Tận dụng khả năng query nhanh chóng cho phân tích real-time trên cơ sở dữ liệu người dùng cực lớn vớ các mô hình data phức tạp bằng các schema linh hoạt và tự động sharding cho mở rộng chiều ngang.</p>



<h2 id="3-uu-diem-va-nhuoc-diem" class="wp-block-heading"><strong>3. Ưu điểm và nhược điểm</strong></h2>



<h2 id="uu-diem" class="wp-block-heading"><strong>Ưu điểm</strong></h2>



<p>Dữ liệu lưu trữ phi cấu trúc, không có tính ràng buộc, toàn vẹn nên tính sẵn sàng cao, hiệu suất lớn và dễ dàng mở rộng lưu trữ.</p>



<p>Dữ liệu được caching (ghi đệm) lên RAM, hạn chế truy cập vào ổ cứng nên tốc độ đọc và ghi cao.</p>



<h2 id="nhuoc-diem" class="wp-block-heading"><strong>Nhược điểm</strong></h2>



<p>Không ứng dụng được cho các mô hình giao dịch nào có yêu cầu độ chính xác cao do không có ràng buộc.</p>



<p>Không có cơ chế transaction (giao dịch) để phục vụ các ứng dụng ngân hàng.</p>



<p>Dữ liệu lấy RAM làm trọng tâm hoạt động vì vậy khi hoạt động yêu cầu một bộ nhớ RAM lớn.</p>



<p>Mọi thay đổi về dữ liệu mặc định đều chưa được ghi xuống ổ cứng ngay lập tức vì vậy khả năng bị mất dữ liệu từ nguyên nhân mất điện đột xuất là rất cao.</p>



<h2 id="4-ket-noi-laravel-mongodb" class="wp-block-heading"><strong>4. Kết nối Laravel + MongoDB</strong></h2>



<h2 id="tao-du-an-laravel" class="wp-block-heading">Tạo dự án laravel</h2>



<p>composer create-project laravel/laravel Demo</p>



<h2 id="them-package-mongodb-vao-du-an" class="wp-block-heading">Thêm package mongoDB vào dự án</h2>



<p>composer require mongodb/laravel-mongodb:4.0.0</p>



<h2 id="them-cau-hinh-mongodb" class="wp-block-heading">Thêm cấu hình mongoDB</h2>



<p>Thêm vào file config/database.php</p>



<pre class="wp-block-code"><code>'connections' =&gt; &#91;
        'mongodb' =&gt; &#91;
            'driver' =&gt; 'mongodb',
            'dsn' =&gt; env('MONGODB_URI'),
            'database' =&gt; 'YOUR_DATABASE_NAME',
        ],</code></pre>



<p>Để lấy các thông tin cấu hình mongoDB truy cập <a href="https://cloud.mongodb.com/v2/659bc617e6426b75883e79c7#/overview">connection mongoDB</a> </p>



<p>Tạo Database</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="348" src="http://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screenshot-from-2024-01-11-22-20-53-1024x348.png" alt="" class="wp-image-3071" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screenshot-from-2024-01-11-22-20-53-1024x348.png 1024w, https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screenshot-from-2024-01-11-22-20-53-300x102.png 300w, https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screenshot-from-2024-01-11-22-20-53-768x261.png 768w, https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screenshot-from-2024-01-11-22-20-53-380x129.png 380w, https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screenshot-from-2024-01-11-22-20-53-800x272.png 800w, https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screenshot-from-2024-01-11-22-20-53.png 1044w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Chọn connect-&gt;Drivers</p>



<figure class="wp-block-image size-full"><img decoding="async" width="828" height="449" src="http://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screenshot-from-2024-01-11-22-29-34.png" alt="" class="wp-image-3072" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screenshot-from-2024-01-11-22-29-34.png 828w, https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screenshot-from-2024-01-11-22-29-34-300x163.png 300w, https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screenshot-from-2024-01-11-22-29-34-768x416.png 768w, https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screenshot-from-2024-01-11-22-29-34-380x206.png 380w, https://blog.tomosia.com.vn/wp-content/uploads/2024/01/Screenshot-from-2024-01-11-22-29-34-800x434.png 800w" sizes="(max-width: 828px) 100vw, 828px" /></figure>



<p>Khi đó bạn sẽ lấy được chuỗi kết nối có dạng như thế này</p>



<pre class="wp-block-code"><code>mongodb+srv://&lt;username&gt;:&lt;password&gt;@test.hlpfzgm.mongodb.net/?retryWrites=true&amp;w=majority</code></pre>



<p>Cập nhật vào file .env</p>



<p>MONGODB_URI=mongodb+srv://&lt;username&gt;:&lt;password&gt;@test.hlpfzgm.mongodb.net/?retryWrites=true&amp;w=majority</p>



<p>Lưu ý: &lt;username&gt; và &lt;password&gt; là username và password đã được nhập ở bước tạo database</p>



<p>Cập nhật vào file config/database.php</p>



<pre class="wp-block-code"><code>'default' =&gt; env('DB_CONNECTION', 'mongodb'),</code></pre>



<h2 id="kiem-tra-ket-noi" class="wp-block-heading">Kiểm tra kết nối</h2>



<pre class="wp-block-code"><code>Route::get('/ping', function (Request  $request) {    
&nbsp;&nbsp;&nbsp;&nbsp;$connection = DB::connection('mongodb');
&nbsp;&nbsp;&nbsp;&nbsp;$msg = 'Thành công!';
&nbsp;&nbsp;&nbsp;&nbsp;try {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$connection-&gt;command(&#91;'ping' =&gt; 1]);  
    } catch (\Exception  $e) {  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$msg = 'Thất bại: ' . $e-&gt;getMessage();
&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;return &#91;'msg' =&gt; $msg];
});</code></pre>



<h2 id="tao-migration-va-model" class="wp-block-heading">Tạo migration và model</h2>



<pre class="wp-block-code"><code>public function up(): void
    {
        Schema::create('customers', function (Blueprint $table) {
            $table-&gt;id();
            $table-&gt;string('name');
            $table-&gt;string('email');
            $table-&gt;string('age');
            $table-&gt;timestamps();
        });
    }</code></pre>



<pre class="wp-block-code"><code>Chạy lệnh:
php artisan migration
php artisan make:model Customer</code></pre>



<pre class="wp-block-code"><code>//use Illuminate\Database\Eloquent\Model;
 use MongoDB\Laravel\Eloquent\Model;

class  Customer  extends  Model
{
&nbsp;&nbsp;&nbsp;&nbsp;use  HasFactory;

    protected  $connection = 'mongodb';

&nbsp;&nbsp;&nbsp;&nbsp;protected  $collection = 'customers';

&nbsp;&nbsp;&nbsp;&nbsp;protected  $fillable = &#91;'name','email','age'];
}</code></pre>



<h2 id="crud" class="wp-block-heading">CRUD</h2>



<pre class="wp-block-code"><code>//Thêm mới
CustomerSQL::create(&#91;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'name'=&gt; 'customer_1',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'email'=&gt; 'customer1@gmail.com',
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'age' =&gt; '18',
]);</code></pre>



<pre class="wp-block-code"><code>//Lấy thông tin customers
Customer::where('name', 'customer_1')-&gt;get();</code></pre>



<p>Hết rồi, hy vọng bài viết có thể giúp ích được cho bạn<br>Cảm ơn và hẹn gặp lại =)) !!!</p>
<p>The post <a href="https://blog.tomosia.com.vn/huong-dan-ket-noi-laravel-mongodb/">Hướng dẫn kết nối Laravel + MongoDB</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/huong-dan-ket-noi-laravel-mongodb/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>Tản mạn về Object Relational Mapping</title>
		<link>https://blog.tomosia.com.vn/tan-man-ve-object-relational-mapping/</link>
					<comments>https://blog.tomosia.com.vn/tan-man-ve-object-relational-mapping/#comments</comments>
		
		<dc:creator><![CDATA[Thien Tran]]></dc:creator>
		<pubDate>Tue, 19 Dec 2023 06:22:34 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[php]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=2238</guid>

					<description><![CDATA[<p>ORM là gì ? ORM là 1 kỹ thuật lập trình giúp ánh xạ các record dữ liệu&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/tan-man-ve-object-relational-mapping/">Tản mạn về Object Relational Mapping</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained">
<h2 id="orm-la-gi" class="wp-block-heading">ORM là gì ?</h2>



<p>ORM là 1 <strong><em>kỹ thuật lập trình</em></strong> giúp ánh xạ các <strong>record</strong> dữ liệu trong hệ quản trị cơ sở dữ liệu sang dạng đối tượng đang định nghĩa trong các class &#8211; một khái niệm phổ biến được sử dụng trong tất cả các ngôn ngữ hiện đại ngày nay như: Java, PHP, Ruby. Bạn có thể áp dụng kĩ thật này với bất cứ dự án nào bạn thích</p>



<figure class="wp-block-image size-full"><img decoding="async" width="700" height="359" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/12/orm.webp" alt="" class="wp-image-2245" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/12/orm.webp 700w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/orm-300x154.webp 300w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/orm-380x195.webp 380w" sizes="(max-width: 700px) 100vw, 700px" /></figure>



<p>Có hai patterns được áp dụng cho các cách thiết kế ORM khác nhau.</p>



<ul class="wp-block-list">
<li>Active Record: Một số ORM nổi tiếng sử dụng như: <strong><em>Eloquent, CachePHP, JOOQ, TOPLINK</em></strong></li>



<li>Data Mapper: Một số ORM nổi tiếng sử dụng như: <strong><em>Doctrine, Hibernate, SqlAlchemy</em></strong></li>
</ul>



<h2 id="orm-hoat-dong-nhu-the-nao" class="wp-block-heading">ORM hoạt động như thế nào ?</h2>



<p>Cơ bản thì ORM gói gọn CSDL trong 1 object, 1 phần sẽ chứa data phần còn lại sẽ xử lý để biến nó thành CSDL quan hệ.</p>



<p>ORM biểu thị các đối tượng ở đó dữ liệu được hiển thị dưới dạng Object</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="735" height="530" src="http://blog.tomosia.com.vn/wp-content/uploads/2023/12/orm1.webp" alt="" class="wp-image-2248" srcset="https://blog.tomosia.com.vn/wp-content/uploads/2023/12/orm1.webp 735w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/orm1-300x216.webp 300w, https://blog.tomosia.com.vn/wp-content/uploads/2023/12/orm1-380x274.webp 380w" sizes="auto, (max-width: 735px) 100vw, 735px" /></figure>
</div></div>



<h2 id="uu-nhuoc-diem-cua-orm" class="wp-block-heading">Ưu nhược điểm của ORM</h2>



<p>Ví dụ về lấy danh sách người dùng cùng với bài đăng mới nhất của mỗi người dù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.854169845581055px;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="$usersWithLatestPosts = DB::select('
    SELECT u.*, p.*
    FROM users u
    LEFT JOIN (
        SELECT user_id, MAX(created_at) AS latest_post_date
        FROM posts
        GROUP BY user_id
    ) latest_posts ON u.id = latest_posts.user_id
    LEFT JOIN posts p ON u.id = p.user_id AND latest_posts.latest_post_date = p.created_at
');" 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">$usersWithLatestPosts </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">DB</span><span style="color: #F286C4">::</span><span style="color: #62E884">select</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #E7EE98">    SELECT u.*, p.*</span></span>
<span class="line"><span style="color: #E7EE98">    FROM users u</span></span>
<span class="line"><span style="color: #E7EE98">    LEFT JOIN (</span></span>
<span class="line"><span style="color: #E7EE98">        SELECT user_id, MAX(created_at) AS latest_post_date</span></span>
<span class="line"><span style="color: #E7EE98">        FROM posts</span></span>
<span class="line"><span style="color: #E7EE98">        GROUP BY user_id</span></span>
<span class="line"><span style="color: #E7EE98">    ) latest_posts ON u.id = latest_posts.user_id</span></span>
<span class="line"><span style="color: #E7EE98">    LEFT JOIN posts p ON u.id = p.user_id AND latest_posts.latest_post_date = p.created_at</span></span>
<span class="line"><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">);</span></span></code></pre></div>



<p>Đây là cách sử dụng ORM trong laravel</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.425346374511719px;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="$usersWithLatestPosts = User::with(['posts' =&gt; function ($query) {
    $query-&gt;latest()-&gt;limit(1);
}])-&gt;get();" 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">$usersWithLatestPosts </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">User</span><span style="color: #F286C4">::</span><span style="color: #62E884">with</span><span style="color: #F6F6F4">([</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">posts</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">function</span><span style="color: #F6F6F4"> ($query) {</span></span>
<span class="line"><span style="color: #F6F6F4">    $query</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">latest</span><span style="color: #F6F6F4">()</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">limit</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">1</span><span style="color: #F6F6F4">);</span></span>
<span class="line"><span style="color: #F6F6F4">}])</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">get</span><span style="color: #F6F6F4">();</span></span></code></pre></div>



<p>Như ví dụ ở trên chúng ta sẽ thấy rõ được 1 số ưu điểm khi sử dụng ORM đó là đoạn code sẽ ngắn gọn hơn, đọc vào dễ hiểu và thân thiện với coder hơn. Đó cũng là một ưu điểm nổi bật của ORM khi được áp dụng vào các dự án.</p>



<p>Ưu điểm:</p>



<ul class="wp-block-list">
<li><strong>Dễ sử dụng và đọc</strong></li>



<li><strong>Tính di động và linh hoạt</strong></li>



<li><strong>Bảo mật dữ liệu</strong></li>



<li><strong>Tương thích với quan hệ đối tượng</strong></li>



<li><strong>Tiết kiệm thời gian phát triển</strong></li>
</ul>



<p>Nhược điểm:</p>



<ul class="wp-block-list">
<li><strong>Hiệu suất không cao nhất</strong></li>



<li><strong>Tùy chỉnh phức tạp</strong></li>



<li><strong>Phụ thuộc vào ORM</strong></li>



<li><strong>Tối ưu hóa không linh hoạt</strong></li>
</ul>



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



<p>Nên mix giữa ORM và Raw SQL sao cho hiệu quả. Với các truy vấn thông thường thì ORM là lựa chọn của mình. Với các tình huống phải thao tác với nhiều bản ghi, raw SQL có vẻ hợp lí hơn. Nhưng khi dùng raw sql bạn phải thực sự cẩn thận về vấn đề Sql Injection.</p>



<p>Cảm ơn các bạn đã theo dõi bài viết trên, trong bài viết có tham khảo từ một số nguồn khác. 🙏🙏🙏</p>
<p>The post <a href="https://blog.tomosia.com.vn/tan-man-ve-object-relational-mapping/">Tản mạn về Object Relational Mapping</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/tan-man-ve-object-relational-mapping/feed/</wfw:commentRss>
			<slash:comments>11</slash:comments>
		
		
			</item>
		<item>
		<title>Có gì mới ở PHP 8.3?</title>
		<link>https://blog.tomosia.com.vn/co-gi-moi-o-php-8-3/</link>
					<comments>https://blog.tomosia.com.vn/co-gi-moi-o-php-8-3/#comments</comments>
		
		<dc:creator><![CDATA[admin_tomosia]]></dc:creator>
		<pubDate>Fri, 15 Dec 2023 09:39:19 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[php]]></category>
		<guid isPermaLink="false">https://blog.tomosia.com.vn/?p=2592</guid>

					<description><![CDATA[<p>PHP 8.3 đã được released vào ngày 23/11/2023 và có nhiều tính năng cũng như cải tiến mới&#8230;</p>
<p>The post <a href="https://blog.tomosia.com.vn/co-gi-moi-o-php-8-3/">Có gì mới ở PHP 8.3?</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>PHP 8.3 đã được released vào ngày 23/11/2023 và có nhiều tính năng cũng như cải tiến mới kể từ khi PHP 8.2 ra mắt. Mặc dù nó chính thức được coi là một bản released nhỏ nhưng một số thay đổi trong 8.3 có thể ảnh hưởng trực tiếp đến công việc của chúng ta với PHP, có thể giúp chúng ta viết mã nhanh hơn và ít lỗi hơn.</p>



<p>Hãy cùng tìm hiểu PHP có những tính năng nào mới và sự thay đổi nào ở bản phát hành mới nhất này.</p>



<h2 id="1-typed-class-constants" class="wp-block-heading">1. Typed Class Constants</h2>



<p>PHP 8.3 trở lên hỗ trợ khai báo kiểu dữ liệu cho các hằng số (constant) class PHP. Điều này đảm bảo tính tương thích về kiểu của các constant khi các class con và các class implement interface ghi đè lên chú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="// Khai báo kiểu dữ liệu sau từ khoá &quot;const&quot;
interface I {
    const string PHP = 'PHP 8.3';
}

class X {
  protected const string FOO = 'foo';
}

trait Y {
  public const string BAR = 'bar';
}" 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">// Khai báo kiểu dữ liệu sau từ khoá &quot;const&quot;</span></span>
<span class="line"><span style="color: #F286C4">interface</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">I</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">string</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">PHP</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">PHP 8.3</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: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">X</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"> </span><span style="color: #F286C4">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">string</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">FOO</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">foo</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: #F286C4">trait</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Y</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">const</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">string</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">BAR</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">bar</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<ul class="wp-block-list">
<li>Điều gì xảy ra nếu giá trị của constant có type khác với type đã khai báo:</li>
</ul>



<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 X {
    const string PHP = 1;
}

// Fatal error: Cannot use int as value for class constant X::PHP of type string" 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">X</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">string</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">PHP</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">1</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: #7B7F8B">// Fatal error: Cannot use int as value for class constant X::PHP of type string</span></span></code></pre></div>



<ul class="wp-block-list">
<li>Ở PHP version trước 8.3, chúng ta có thể override lại giá trị của constant khi triển khai interface hoặc class cha:</li>
</ul>



<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 I {
    const PHP = 'PHP 8.2';
}

class Foo implements I {
    const PHP = [];
}" 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">I</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">PHP</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">PHP 8.2</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: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Foo</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">implements</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">I</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">PHP</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></code></pre></div>



<ul class="wp-block-list">
<li>Nhưng PHP 8.3 đã ngăn chặn việc thay đổi type của constant không tương thích với type đã khai báo ở interface hoặc class cha:</li>
</ul>



<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="interface I {
    const string PHP = 'PHP 8.3';
}

class Foo implements I {

    // Illegal
    // Fatal error: Cannot use array as value for class constant Foo::PHP       
    // of type string
    const string PHP = [];
    
    // Illegal:
    // Type must be declared if it was specified in the base class
    const PHP = &quot;PHP 8.3&quot;;

    // Illegal:
    // In this case, we can't change the type declared in the 
    // base class, even if the new type and its value are compatible.
    const float PHP = 8.3;
    
    // Legal:
    // It's OK
    const string PHP = &quot;PHP 8.3.x.y.z&quot;;
}
" 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">I</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">string</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">PHP</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">PHP 8.3</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: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Foo</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">implements</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">I</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Illegal</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Fatal error: Cannot use array as value for class constant Foo::PHP       </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// of type string</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">string</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">PHP</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>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Illegal:</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Type must be declared if it was specified in the base class</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">PHP</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">PHP 8.3</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Illegal:</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// In this case, we can&#39;t change the type declared in the </span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// base class, even if the new type and its value are compatible.</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">float</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">PHP</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">8.3</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">// Legal:</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// It&#39;s OK</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">string</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">PHP</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">PHP 8.3.x.y.z</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span>
<span class="line"></span></code></pre></div>



<ul class="wp-block-list">
<li>Chúng ta có thể khai báo nhiều kiểu theo dạng &#8220;narrowed&#8221;:</li>
</ul>



<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 Foo {
    public const string|int FOO = 'foo';
}

class Bar extends Foo {
    public const string FOO = 'bar';
    public const int FOO = 8;
    
    // Illegal:
    // Không thể mở rộng thêm types ở class con
    public const string|int|float FOO = 8;
}" 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">Foo</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">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">string</span><span style="color: #F286C4">|</span><span style="color: #97E1F1; font-style: italic">int</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">FOO</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">foo</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: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Bar</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">extends</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Foo</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">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">string</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">FOO</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">bar</span><span style="color: #DEE492">&#39;</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">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">int</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">FOO</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">8</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">// Illegal:</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #7B7F8B">// Không thể mở rộng thêm types ở class con</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">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">string</span><span style="color: #F286C4">|</span><span style="color: #97E1F1; font-style: italic">int</span><span style="color: #F286C4">|</span><span style="color: #97E1F1; font-style: italic">float</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">FOO</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">8</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p>❗️ Hai types <strong><em>void</em></strong> và <em><strong>never</strong></em> không được hỗ trợ khi khai báo constant.</p>



<h2 id="2-dynamic-class-constant-fetch" class="wp-block-heading">2. <strong>Dynamic class constant fetch</strong></h2>



<ul class="wp-block-list">
<li>Việc fetch các constants, có thể sử dụng hàm <code>constant()</code>. Ở PHP version trước 8.3, chúng ta sẽ làm thế này:</li>
</ul>



<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 Foo {
    public const THE_FOO = 9;
}

enum FooEnum: int {
    case FirstMember = 9;
    case SecondMember = 10;
}

$constantName = 'THE_FOO';
$enumName = 'FirstMember';

echo constant('Foo::' . $constantName); // 9
echo constant('FooEnum::' . $enumName)-&gt;value; // 9" 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">Foo</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">const</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">THE_FOO</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">9</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">enum</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">FooEnum</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">int</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">case</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">FirstMember</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">9</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">case</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">SecondMember</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">=</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">}</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">$constantName </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">THE_FOO</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F6F6F4">$enumName </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">FirstMember</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">constant</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">Foo::</span><span style="color: #DEE492">&#39;</span><span style="color: #62E884"> </span><span style="color: #F286C4">.</span><span style="color: #62E884"> </span><span style="color: #F6F6F4">$constantName); </span><span style="color: #7B7F8B">// 9</span></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">constant</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">FooEnum::</span><span style="color: #DEE492">&#39;</span><span style="color: #62E884"> </span><span style="color: #F286C4">.</span><span style="color: #62E884"> </span><span style="color: #F6F6F4">$enumName)</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">value; </span><span style="color: #7B7F8B">// 9</span></span></code></pre></div>



<ul class="wp-block-list">
<li>Từ PHP 8.3 trở đi, chúng ta có thể fetch chúng một cách linh động và gọn gàng hơn:</li>
</ul>



<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="echo Foo::{$constantName};
echo FooEnum::{$enumName}-&gt;value;" 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">echo</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Foo</span><span style="color: #F286C4">::</span><span style="color: #F6F6F4">{$constantName};</span></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">FooEnum</span><span style="color: #F286C4">::</span><span style="color: #F6F6F4">{$enumName}</span><span style="color: #F286C4">-&gt;</span><span style="color: #F6F6F4">value;</span></span></code></pre></div>



<h2 id="3-json_validate-function" class="wp-block-heading">3. <code>json_validate</code>()&nbsp;function</h2>



<p>Khi làm việc với dữ liệu JSON-encoded, chúng ta muốn biết liệu phần payload có hợp lệ về mặt cú pháp hay không trước khi làm điều gì đó với nó.</p>



<ul class="wp-block-list">
<li>Trước PHP 8.3, cách duy nhất để xác định xem một chuỗi có phải là chuỗi JSON hợp lệ hay không là cố gắng decode nó và xem liệu có lỗi nào không:</li>
</ul>



<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="function json_check(string $string): bool {
    json_decode($string);

    return json_last_error() === JSON_ERROR_NONE;
}

$string = '{ &quot;test&quot;: { &quot;foo&quot;: &quot;bar&quot; } '
echo json_check($string); // false" 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">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">json_check</span><span style="color: #F6F6F4">(</span><span style="color: #F286C4">string</span><span style="color: #F6F6F4"> $string)</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">bool</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #97E1F1">json_decode</span><span style="color: #F6F6F4">($string);</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: #97E1F1">json_last_error</span><span style="color: #F6F6F4">() </span><span style="color: #F286C4">===</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">JSON_ERROR_NONE</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">$string </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">{ &quot;test&quot;: { &quot;foo&quot;: &quot;bar&quot; } </span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">json_check</span><span style="color: #F6F6F4">($string); </span><span style="color: #7B7F8B">// false</span></span></code></pre></div>



<ul class="wp-block-list">
<li>Ở PHP 8.3 này,  một hàm mới được bổ sung có tên <code>json_validate()</code> trả về <code>true</code> hoặc <code>false</code> để kiểm tra chuỗi đã cho có phải là chuỗi JSON hợp lệ hay không:</li>
</ul>



<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="$string = '{ &quot;test&quot;: { &quot;foo&quot;: &quot;bar&quot; } '
echo json_validate($string); // false" 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">$string </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">{ &quot;test&quot;: { &quot;foo&quot;: &quot;bar&quot; } </span><span style="color: #DEE492">&#39;</span></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">json_validate</span><span style="color: #F6F6F4">($string); </span><span style="color: #7B7F8B">// false</span></span></code></pre></div>



<ul class="wp-block-list">
<li>Nếu <code>json_validate() </code>trả về <code>false</code>, nguyên nhân có thể được truy xuất bằng cách sử dụng <code>json_last_error()</code> và <code>json_last_error_msg()</code>.</li>
</ul>



<p>❗️<strong>Important: </strong>Nếu bạn không làm gì với những thuộc tính trong payload của chuỗi JSON và chỉ cần kiểm tra JSON có hợp lệ hay không để làm 1 việc gì đó (insert vào DB chẳng hạn), thì sử dụng <code>json_validate()</code> sẽ sử dụng ít bộ nhớ hơn <code>json_decode()</code>, vì nó không cần phải mã hoá hay xây dựng cấu trúc array/object trong chuỗi JSON trên.</p>



<h2 id="4-override-attribute" class="wp-block-heading">4. <code>#[\Override]</code><strong>&nbsp;attribute</strong></h2>



<p>Giả sử chúng ta muốn override method <code>test()</code> của lớp cha, nhưng lại gõ sai thành <code>best()</code>, việc này ngầm hiểu là tạo ra method mới có tên là <code>best()</code>, không đúng mục đích ban đầu là override lại method <code>test()</code>.</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 Parent {
  protected function test(): void {}
}

class Child extends Parent {
  public function best(): void {}
}" 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">Parent</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"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">test</span><span style="color: #F6F6F4">()</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">void</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">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Child</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">extends</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Parent</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">best</span><span style="color: #F6F6F4">()</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">void</span><span style="color: #F6F6F4"> {}</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p>PHP 8.3 cung cấp một thuộc tính mới có tên<code> #[\Override]</code> có thể được thêm vào các method class. </p>



<ul class="wp-block-list">
<li>Khi thuộc tính <code>#[\Override]</code> được thêm vào một method class có extend class cha hoặc implement một interface, PHP bắt buộc rằng method đó phải override hoặc triển khai method của class cha hoặc interface.</li>



<li>Mục đích là để ngăn chặn việc chúng ta muốn override/triển khai method của class cha nhưng lại vô tình viết sai tên method hoặc method đó đã bị xoá khỏi lớp cha.</li>
</ul>



<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 Parent {
  protected function test(): void {}
}

class Child extends Parent {
  #[\Override]
  public function test(): void {}
  // Good
}

class Grand extends Parent {
  #[\Override]
  public function best(): void {}
  // Bad:
  // Fatal error: Grand::best() has #[\Override] attribute,
  // but no matching parent method exists
}" 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">Parent</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"> </span><span style="color: #F286C4">function</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">test</span><span style="color: #F6F6F4">()</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">void</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">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Child</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">extends</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Parent</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">  #[</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Override</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">test</span><span style="color: #F6F6F4">()</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">void</span><span style="color: #F6F6F4"> {}</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #7B7F8B">// Good</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">Grand</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">extends</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">Parent</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">  #[</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Override</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">best</span><span style="color: #F6F6F4">()</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">void</span><span style="color: #F6F6F4"> {}</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #7B7F8B">// Bad:</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #7B7F8B">// Fatal error: Grand::best() has #[\Override] attribute,</span></span>
<span class="line"><span style="color: #F6F6F4">  </span><span style="color: #7B7F8B">// but no matching parent method exists</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<h2 id="5-deep-cloning-of-readonly-properties" class="wp-block-heading">5. Deep Cloning of&nbsp;<code>readonly</code>&nbsp;Properties</h2>



<p>Trong PHP 8.1, các thuộc tính <code>readonly</code> đã được giới thiệu, tiếp theo là class <code>readonly</code> trong PHP 8.2. </p>



<p>Một vấn đề khác là khi clone các đối tượng. Việc clone các đối tượng và thuộc tính <code>readonly</code> là điều không thể.</p>



<p>Kể từ PHP 8.3, bạn có thể linh hoạt khởi tạo lại hoặc unset các thuộc tính <code>readonly</code> trong quá trình clone.</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="readonly class Foo
{
    public function __construct(private DateTime $createdAt)
    {
    }

    public function getCreatedAt(): DateTime
    {
        return $this-&gt;createdAt;
    }

    public function __clone(): void
    {
        $this-&gt;createdAt = clone $this-&gt;createdAt;
    }
}

$instance = new Foo(new DateTime('2023-12-15'));
$cloned = clone $instance;

// For PHP &lt; 8.3:
// PHP Fatal error: Uncaught Error: Cannot modify readonly 
// property Foo::$createdAt in Foo.php

// For PHP 8.3:
$cloned = clone $instance;
$cloned-&gt;getCreatedAt()-&gt;setDate(2023, 12, 16);" 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">readonly</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">class</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">Foo</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: #97E1F1">__construct</span><span style="color: #F6F6F4">(</span><span style="color: #F286C4">private</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">DateTime</span><span style="color: #F6F6F4"> $createdAt)</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: #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">getCreatedAt</span><span style="color: #F6F6F4">()</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">DateTime</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">createdAt;</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: #BF9EEE">__clone</span><span style="color: #F6F6F4">()</span><span style="color: #F286C4">:</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">void</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">createdAt </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">clone</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">createdAt;</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: #F6F6F4">$instance </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">Foo</span><span style="color: #F6F6F4">(</span><span style="color: #F286C4">new</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">DateTime</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">2023-12-15</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">));</span></span>
<span class="line"><span style="color: #F6F6F4">$cloned </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">clone</span><span style="color: #F6F6F4"> $instance;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #7B7F8B">// For PHP &lt; 8.3:</span></span>
<span class="line"><span style="color: #7B7F8B">// PHP Fatal error: Uncaught Error: Cannot modify readonly </span></span>
<span class="line"><span style="color: #7B7F8B">// property Foo::$createdAt in Foo.php</span></span>
<span class="line"></span>
<span class="line"><span style="color: #7B7F8B">// For PHP 8.3:</span></span>
<span class="line"><span style="color: #F6F6F4">$cloned </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #F286C4">clone</span><span style="color: #F6F6F4"> $instance;</span></span>
<span class="line"><span style="color: #F6F6F4">$cloned</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getCreatedAt</span><span style="color: #F6F6F4">()</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">setDate</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">2023</span><span style="color: #F6F6F4">, </span><span style="color: #BF9EEE">12</span><span style="color: #F6F6F4">, </span><span style="color: #BF9EEE">16</span><span style="color: #F6F6F4">);</span></span></code></pre></div>



<h2 id="6-randomizergetbytesfromstring-method" class="wp-block-heading">6.<strong>&nbsp;</strong><code>Randomizer::getBytesFromString()</code><strong>&nbsp;method</strong></h2>



<p>PHP 8.3 hỗ trợ phương thức <code>Randomizer::getBytesFromString()</code> mới trả về một chuỗi số ngẫu nhiên từ chuỗi đầu vào và có độ dài được yêu cầu.</p>



<p>Cơ hội để một byte được chọn tỷ lệ thuận với tỷ lệ xuất hiện của nó trong chuỗi đầu vào. Nếu mỗi byte xuất hiện với số lần như nhau thì mỗi byte đều có khả năng được chọn như nhau.</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="$random = new Random\Randomizer();
$alpha = 'ABCDEFGHJKMNPQRSTVWXYZ';

$random-&gt;getBytesFromString($alpha, 6); //  &quot;MBXGWL&quot;
$random-&gt;getBytesFromString($alpha, 6); //  &quot;LESPMG&quot;

$randomDomain = sprintf(
    &quot;%s.example.com&quot;,
    $randomizer-&gt;getBytesFromString(
        'abcdefghijklmnopqrstuvwxyz0123456789',
        16,
    ),
);

echo $randomDomain;" 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">$random </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">Random</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Randomizer</span><span style="color: #F6F6F4">();</span></span>
<span class="line"><span style="color: #F6F6F4">$alpha </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">ABCDEFGHJKMNPQRSTVWXYZ</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">$random</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getBytesFromString</span><span style="color: #F6F6F4">($alpha, </span><span style="color: #BF9EEE">6</span><span style="color: #F6F6F4">); </span><span style="color: #7B7F8B">//  &quot;MBXGWL&quot;</span></span>
<span class="line"><span style="color: #F6F6F4">$random</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getBytesFromString</span><span style="color: #F6F6F4">($alpha, </span><span style="color: #BF9EEE">6</span><span style="color: #F6F6F4">); </span><span style="color: #7B7F8B">//  &quot;LESPMG&quot;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">$randomDomain </span><span style="color: #F286C4">=</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1">sprintf</span><span style="color: #F6F6F4">(</span></span>
<span class="line"><span style="color: #62E884">    </span><span style="color: #DEE492">&quot;</span><span style="color: #E7EE98">%s.example.com</span><span style="color: #DEE492">&quot;</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #62E884">    </span><span style="color: #F6F6F4">$randomizer</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getBytesFromString</span><span style="color: #F6F6F4">(</span></span>
<span class="line"><span style="color: #62E884">        </span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">abcdefghijklmnopqrstuvwxyz0123456789</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #62E884">        </span><span style="color: #BF9EEE">16</span><span style="color: #F6F6F4">,</span></span>
<span class="line"><span style="color: #62E884">    </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: #97E1F1">echo</span><span style="color: #F6F6F4"> $randomDomain;</span></span></code></pre></div>



<p>Lưu ý rằng phương thức <code>Randomizer::getBytesFromString()</code> hoạt động ở cấp độ byte. Nó không thể xáo trộn một cách hiệu quả các ký tự nhiều byte như biểu tượng cảm xúc, ký tự CJK.</p>



<h2 id="7-randomizergetfloat-and-randomizernextfloat-method" class="wp-block-heading">7.<strong>&nbsp;</strong><code>Randomizer::<code>getFloat</code>()</code> and <code>Randomizer::<code>nextFloat</code>()</code> <strong>method</strong></h2>



<p>PHP 8.3 thêm các phương thức <code>Randomizer::getFloat()</code> và <code>Randomizer::nextFloat()</code> tạo ra giá trị float ngẫu nhiên.</p>



<h3 id="7-1-randomizergetfloat" class="wp-block-heading">7.1. <code>Randomizer::getFloat()</code></h3>



<ul class="wp-block-list">
<li>Ví dụ, generate 1 số float có khoảng giá trị 0 -&gt; 5:</li>
</ul>



<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="$random = new Random\Randomizer();

$random-&gt;getFloat(0, 5); // 2.3937446906217" 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">$random </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">Random</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Randomizer</span><span style="color: #F6F6F4">();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">$random</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getFloat</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">0</span><span style="color: #F6F6F4">, </span><span style="color: #BF9EEE">5</span><span style="color: #F6F6F4">); </span><span style="color: #7B7F8B">// 2.3937446906217</span></span></code></pre></div>



<p>Phương thức <code>Randomizer::getFloat()</code> chấp nhận <code>\Random\IntervalBoundary</code> Enum làm tham số thứ ba để cho biết liệu các giá trị <code>min</code> và <code>max</code> có phải bao gồm ở kết quả trả về hay khô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="enum IntervalBoundary {
    case ClosedOpen;
    case ClosedClosed;
    case OpenClosed;
    case OpenOpen;
}" 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">enum</span><span style="color: #F6F6F4"> </span><span style="color: #97E1F1; font-style: italic">IntervalBoundary</span><span style="color: #F6F6F4"> {</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">case</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">ClosedOpen</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">case</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">ClosedClosed</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">case</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">OpenClosed</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F6F6F4">    </span><span style="color: #F286C4">case</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">OpenOpen</span><span style="color: #F6F6F4">;</span></span>
<span class="line"><span style="color: #F6F6F4">}</span></span></code></pre></div>



<p>Rules như sau:</p>



<ul class="wp-block-list">
<li><code>IntervalBoundary::ClosedOpen</code>: <em>$min</em> có thể được return, <em>$max</em> có thể <strong>không</strong>.</li>



<li><code>IntervalBoundary::ClosedClosed</code>: cả <em>$min</em> và <em>$max</em> đều có thể được return.</li>



<li><code>IntervalBoundary::OpenClosed</code>: <em>$min</em> có thể <strong>không được </strong>return, <em>$max</em> có thể.</li>



<li><code>IntervalBoundary::OpenOpen</code>: Cả <em>$min</em> và <em>$max</em> đều <strong>không được</strong> return.</li>
</ul>



<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="$random = new Random\Randomizer();

$random-&gt;getFloat(0, 10, \Random\IntervalBoundary::OpenOpen); 
// 9.3835746900717" 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">$random </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">Random</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Randomizer</span><span style="color: #F6F6F4">();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">$random</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">getFloat</span><span style="color: #F6F6F4">(</span><span style="color: #BF9EEE">0</span><span style="color: #F6F6F4">, </span><span style="color: #BF9EEE">10</span><span style="color: #F6F6F4">, </span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Random</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">IntervalBoundary</span><span style="color: #F286C4">::</span><span style="color: #BF9EEE">OpenOpen</span><span style="color: #F6F6F4">); </span></span>
<span class="line"><span style="color: #7B7F8B">// 9.3835746900717</span></span></code></pre></div>



<h3 id="7-2-randomizernextfloat" class="wp-block-heading">7.2. <code>Randomizer::nextFloat()</code></h3>



<p>Method <code>Randomizer::nextFloat()</code> mới có chức năng giống hệt với <code>Randomizer::getFloat(0, 1, \Random\IntervalBoundary::ClosedOpen</code>), trả về một giá trị ngẫu nhiên trong phạm vi <code>0 &lt;= x &lt; 1</code></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="$random = new Random\Randomizer();

$random-&gt;nextFloat(); // 0.3767414902847" 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">$random </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">Random</span><span style="color: #F286C4; font-style: italic">\</span><span style="color: #97E1F1; font-style: italic">Randomizer</span><span style="color: #F6F6F4">();</span></span>
<span class="line"></span>
<span class="line"><span style="color: #F6F6F4">$random</span><span style="color: #F286C4">-&gt;</span><span style="color: #62E884">nextFloat</span><span style="color: #F6F6F4">(); </span><span style="color: #7B7F8B">// 0.3767414902847</span></span></code></pre></div>



<h2 id="8-php-cli-lint-php-l-supports-linting-multiple-files-at-once" class="wp-block-heading">8. PHP CLI Lint (<code>php -l</code>) supports linting multiple files at once</h2>



<p>PHP CLI cung cấp tính năng Linting để kiểm tra tên tệp đã truyền để tìm lỗi syntax. Điều này rất hữu ích để kiểm tra nhanh tệp PHP hoặc đoạn mã trước khi thực thi.</p>



<ul class="wp-block-list">
<li>Ở PHP &lt; 8.3, chỉ thực hiện kiểm tra lỗi syntax ở file đầu tiên được khai báo:</li>
</ul>



<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">Zsh</span><span role="button" tabindex="0" data-code="php -l foo.php bar.php
No syntax errors detected in foo.php" 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: #62E884">php</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">-l</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">foo.php</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">bar.php</span></span>
<span class="line"><span style="color: #62E884">No</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">syntax</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">errors</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">detected</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">in</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">foo.php</span></span></code></pre></div>



<ul class="wp-block-list">
<li>Ở PHP 8.3:</li>
</ul>



<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">Zsh</span><span role="button" tabindex="0" data-code="php -l foo.php bar.php
No syntax errors detected in foo.php
No syntax errors detected in bar.php" 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: #62E884">php</span><span style="color: #F6F6F4"> </span><span style="color: #BF9EEE">-l</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">foo.php</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">bar.php</span></span>
<span class="line"><span style="color: #62E884">No</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">syntax</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">errors</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">detected</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">in</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">foo.php</span></span>
<span class="line"><span style="color: #62E884">No</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">syntax</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">errors</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">detected</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">in</span><span style="color: #F6F6F4"> </span><span style="color: #E7EE98">bar.php</span></span></code></pre></div>



<h2 id="9-mb_str_pad-function" class="wp-block-heading">9. <code>mb_str_pad()</code> function </h2>



<p>PHP cung cấp hàm <code>str_pad</code> được sử dụng để đệm một chuỗi đến một độ dài xác định bằng một chuỗi khác.</p>



<p>Tuy nhiên, hàm <code>str_pad</code> không hỗ trợ các ký tự nhiều byte, dẫn đến các vấn đề khi xử lý các ngôn ngữ sử dụng mã hóa nhiều byte như UTF-8.</p>



<p>Kể từ PHP 8.3, hàm <code>mb_str_pad</code> được cung cấp để giải quyết hạn chế trước đó của hàm <code>str_pad</code> trong việc xử lý mã hóa ký tự nhiều byte như UTF-8.</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="echo mb_str_pad('卞卞', 6, '义', STR_PAD_BOTH); 
// 义义卞卞义义

echo mb_str_pad('▶▶', 6, '❤❓❇', STR_PAD_RIGHT); 
 // string(18) &quot;▶▶❤❓❇❤&quot;
 
echo mb_str_pad('▶▶', 6, '❤❓❇', STR_PAD_LEFT);  
// string(18) &quot;❤❓❇❤▶▶&quot;" 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">echo</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">mb_str_pad</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: #62E884"> </span><span style="color: #BF9EEE">6</span><span style="color: #F6F6F4">,</span><span style="color: #62E884"> </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: #62E884"> </span><span style="color: #BF9EEE">STR_PAD_BOTH</span><span style="color: #F6F6F4">); </span></span>
<span class="line"><span style="color: #7B7F8B">// 义义卞卞义义</span></span>
<span class="line"></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">mb_str_pad</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: #62E884"> </span><span style="color: #BF9EEE">6</span><span style="color: #F6F6F4">,</span><span style="color: #62E884"> </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: #62E884"> </span><span style="color: #BF9EEE">STR_PAD_RIGHT</span><span style="color: #F6F6F4">); </span></span>
<span class="line"><span style="color: #F6F6F4"> </span><span style="color: #7B7F8B">// string(18) &quot;▶▶❤❓❇❤&quot;</span></span>
<span class="line"><span style="color: #F6F6F4"> </span></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">mb_str_pad</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: #62E884"> </span><span style="color: #BF9EEE">6</span><span style="color: #F6F6F4">,</span><span style="color: #62E884"> </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: #62E884"> </span><span style="color: #BF9EEE">STR_PAD_LEFT</span><span style="color: #F6F6F4">);  </span></span>
<span class="line"><span style="color: #7B7F8B">// string(18) &quot;❤❓❇❤▶▶&quot;</span></span></code></pre></div>



<h2 id="10-str_increment-str_decrement-functions" class="wp-block-heading">10. str_increment(), str_decrement() functions</h2>



<p>Kể từ PHP 8.3, các hàm <code>str_increment</code> có thể được sử dụng tăng một chuỗi chữ và số, và hàm <code>str_decrement</code> giảm một chuỗi chữ và số. </p>



<p>Các hàm này có thể đặc biệt hữu ích trong các tình huống mà bạn cần quản lý các chuỗi chữ và số đại diện cho các giá trị tuần 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="echo str_increment('ABC'); // ABD
echo str_decrement('ABC'); // ABB
echo str_increment('39'); // 40
echo str_decrement('38'); // 37" 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">echo</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">str_increment</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">ABC</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">); </span><span style="color: #7B7F8B">// ABD</span></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">str_decrement</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">ABC</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">); </span><span style="color: #7B7F8B">// ABB</span></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">str_increment</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">39</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">); </span><span style="color: #7B7F8B">// 40</span></span>
<span class="line"><span style="color: #97E1F1">echo</span><span style="color: #F6F6F4"> </span><span style="color: #62E884">str_decrement</span><span style="color: #F6F6F4">(</span><span style="color: #DEE492">&#39;</span><span style="color: #E7EE98">38</span><span style="color: #DEE492">&#39;</span><span style="color: #F6F6F4">); </span><span style="color: #7B7F8B">// 37</span></span></code></pre></div>



<p>Vẫn còn một vài tính năng mới và thay đổi trong version này, mọi người có thể xem thêm tại: <a href="https://www.php.net/releases/8.3/en.php#other_new_things" target="_blank" rel="noreferrer noopener">https://www.php.net/releases/8.3/en.php#other_new_things</a><br><br>Cảm ơn mọi người đã dành thời gian để đọc 🙇‍♂️<br><br></p>
<p>The post <a href="https://blog.tomosia.com.vn/co-gi-moi-o-php-8-3/">Có gì mới ở PHP 8.3?</a> appeared first on <a href="https://blog.tomosia.com.vn">Tomoshare</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.tomosia.com.vn/co-gi-moi-o-php-8-3/feed/</wfw:commentRss>
			<slash:comments>6</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[Laravel]]></category>
		<category><![CDATA[php]]></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>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>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>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>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><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>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>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>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>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>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>Đâ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>Dưới đây là một số operator mà thư viện hỗ trợ</p>



<figure class="wp-block-image size-large"><img loading="lazy" 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="auto, (max-width: 799px) 100vw, 799px" /></figure>



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



<p>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>Đâ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>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><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></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>5</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[Kinh nghiệm]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[SOLID]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[php]]></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>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>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><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>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>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>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>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>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>Đị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>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><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>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>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>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><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>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>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>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>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>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>Ở 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>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>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>Đ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>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><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>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>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>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>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>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>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><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>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>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>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>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>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><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>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>10</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[s3]]></category>
		<category><![CDATA[Laravel]]></category>
		<category><![CDATA[php]]></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></p>



<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 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> Giả sử chúng ta có 1000 files cần upload lên S3 Storage. </p>



<p>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>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>Để 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>Đầ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>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>Ở đâ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>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>Đố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><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>4</slash:comments>
		
		
			</item>
	</channel>
</rss>
