Feat: Add `Article` and `Author` Models and migrations

The `Author` model relates to the pre-defined `User` model and the two
new models relate to each other as expected.
This commit is contained in:
Jonathan Nielson 2024-02-04 20:36:25 -06:00
parent 229caa9614
commit b1fb5f09b7
4 changed files with 182 additions and 0 deletions

34
app/Models/Article.php Normal file
View File

@ -0,0 +1,34 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Article extends Model
{
use HasFactory;
/** The name of the database table storing this Model's records. */
protected string $table = 'articles';
/** The attributes on the Model that can be mass-assigned */
protected array $fillable = [
'title',
'subtitle',
'author_id',
'slug',
'body',
'published_at',
'header_image_url',
'path_to_markdown_source',
'processed_at',
];
/** The person that wrote the article. */
public function author(): BelongsTo
{
return $this->belongsTo(Author::class);
}
}

39
app/Models/Author.php Normal file
View File

@ -0,0 +1,39 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Author extends Model
{
use HasFactory;
/** The name of the database table storing this Model's records. */
protected string $table = 'authors';
/** The attributes on the Model that can be mass-assigned */
protected array $fillable = [
'display_name',
'profile_image_url',
'user_id',
'biography',
'primary_link',
'secondary_link',
'mastodon_handle',
];
/** The application-level User account of this writer */
public function user(): HasOne
{
return $this->hasOne(User::class);
}
/** All the Articles this person has written */
public function articles(): HasMany
{
return $this->hasMany(Article::class);
}
}

View File

@ -0,0 +1,58 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('articles', function (Blueprint $table) {
$table->id();
$table->string('title', 255);
// The URL-encoded version of the title, more or less. Also acts as
// the unique, public-facing identifier for the article
$table->string('slug', 255);
$table->foreignId('author_id')
->constrained(table: 'authors', indexName: 'articles_authors_id')
->onUpdate('cascade')
->onDelete('cascade');
$table->string('subtitle', 255)->nullable();
// The HTML-formatted version of the body, ready for browser display
$table->longText('body');
// The dateTime when the article was made public to the world. If
// it's in the future or doesn't exist, the article hasn't been
// published yet
$table->dateTime('published_at')->nullable();
$table->string('header_image_url', 255)->nullable();
// The path on the server disk to the original markdown file.
$table->string('path_to_markdown_source');
// The dateTime when the original markdown file was parsed and the
// HTML body was generated (among other things)
$table->dateTime('processed_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('articles');
}
};

View File

@ -0,0 +1,51 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('authors', function (Blueprint $table) {
$table->id();
// Since we're separating authors and Word Salad User's as entities, this will strictly control how their
// name appears in authorial contexts.
$table->string('display_name', 100);
// The link the author's profile picture
$table->string('profile_image_url')->nullable();
$table->foreignId('user_id')
->constrained(table: 'users', indexName: 'authors_user_id')
->onUpdate('cascade')
->onDelete('cascade')
->nullable();
// An introductory paragraph or two of the author
$table->text('biography')->nullable();
// A URL to the author's primary home on the web, a special shout out, whatever
$table->string('primary_link', 120)->nullable();
$table->string('secondary_link', 120)->nullable();
$table->string('mastodon_handle', 200)->nullable();
// created_at and updated_at timestamps
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('authors');
}
};