Track and display subdomains under their root domain
Adds sites.root_domain (indexed string, backfilled for existing rows)
computed via a naive "last two labels" heuristic (App\Support\RootDomain)
— good enough for example.com/somesite.es, but wrong for two-part
public suffixes like .co.uk. Doing that correctly needs the Mozilla
Public Suffix List; flagged as a known simplification rather than
built now.
Deliberately not a hard FK: like Backlink.target_domain, a subdomain
can get indexed before its root domain does (or vice versa), so
Site::subdomains()/rootSite() match on the domain string rather than
requiring the relationship to exist at write time.
Site detail page: a root domain shows a paginated "Subdomains"
section (same guest-preview cap as Pages/Backlinks); a subdomain
shows "Subdomain of {root}" linking back, when the root is itself
indexed.
Verified against real data: 21k.ro correctly lists its two known
subdomains (buzau.21k.ro, timisoara.21k.ro), each of which correctly
links back to 21k.ro. Added SubdomainsTest (root lists subdomains,
subdomain links to root, empty state) — full suite (31 tests) passes.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
use App\Support\RootDomain;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* root_domain lets a site's subdomains be found without a hard FK (which would
|
||||
* need backfilling later if the root domain gets crawled after its subdomains do)
|
||||
* — same reasoning as Backlink.target_domain being a plain indexed string rather
|
||||
* than a foreign key to a site that might not exist yet.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('sites', function (Blueprint $table) {
|
||||
$table->string('root_domain')->nullable()->after('domain');
|
||||
});
|
||||
|
||||
DB::table('sites')->orderBy('id')->select('id', 'domain')->chunkById(500, function ($rows) {
|
||||
foreach ($rows as $row) {
|
||||
DB::table('sites')->where('id', $row->id)->update(['root_domain' => RootDomain::of($row->domain)]);
|
||||
}
|
||||
});
|
||||
|
||||
Schema::table('sites', function (Blueprint $table) {
|
||||
$table->string('root_domain')->nullable(false)->change();
|
||||
$table->index('root_domain');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('sites', function (Blueprint $table) {
|
||||
$table->dropIndex(['root_domain']);
|
||||
$table->dropColumn('root_domain');
|
||||
});
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user