<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Paul's Brain Dump]]></title><description><![CDATA[Whenever I learn something, I find I understand it better if I write it out like I'm explaining it to somebody else. Also, it's handy if I come back to it twelv]]></description><link>https://pauls-brain-dump.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Wed, 04 Nov 2026 13:02:59 GMT</lastBuildDate><atom:link href="https://pauls-brain-dump.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[PHP Enumerations]]></title><description><![CDATA[Enumerations were added to PHP in PHP 8.1 so I decided to give them a try, and I quite like them. Here’s the most basic form So now you can do and You…]]></description><link>https://pauls-brain-dump.hashnode.dev/php-enumerations</link><guid isPermaLink="true">https://pauls-brain-dump.hashnode.dev/php-enumerations</guid><category><![CDATA[PHP]]></category><category><![CDATA[enum]]></category><category><![CDATA[php8]]></category><dc:creator><![CDATA[Paul Hunter]]></dc:creator><pubDate>Mon, 02 Nov 2026 14:40:50 GMT</pubDate><content:encoded><![CDATA[<p>Enumerations were added to PHP in PHP 8.1 so I decided to give them a try, and I quite like them.</p>
<p>Here’s the most basic form</p>
<pre><code class="language-php">enum MaritalStatus {
  case Single;
  case Married;
  case Divorced;
  case Separated;
  case Widowed;
}
</code></pre>
<p>So now you can do</p>
<pre><code class="language-php">$employeeMaritalStatus = MaritalStatus::Married;
</code></pre>
<p>and</p>
<pre><code class="language-php">if ($employeeMaritalStatus == MaritalStatus::Married) {
  echo 'Employee is married';
}
</code></pre>
<p>You can’t do</p>
<pre><code class="language-php">echo $employeeMaritalStatus;
</code></pre>
<p>because an enum isn’t a string, and it’s not automatically convertible into a string, but you can do</p>
<pre><code class="language-php">echo $employeeMaritalStatus-&gt;name;
</code></pre>
<p>which will get you a string value like “Married”, “Single”, etc.</p>
<p>The first thing you might want to do is produce a human-readable display version of that, e.g. “Divorced/Civil Partnership Dissolved” instead of “Divorced”.</p>
<p>That’s called a <em>backed enumeration</em>, so it becomes this</p>
<pre><code class="language-php">enum MaritalStatus: string {
  case Single = 'Single';
  case Married = 'Married/Civil Partner';
  case Divorced = 'Divorced/Civil Partnership Dissolved';
  case Separated = 'Separated';
  case Widowed = 'Widowed/Surviving Civil Partner';
}
</code></pre>
<p>You still can’t do</p>
<pre><code class="language-php">echo $employeeMaritalStatus;
</code></pre>
<p>But you can now do</p>
<pre><code class="language-php">echo $employeeMaritalStatus-&gt;name;
</code></pre>
<p>which will get you “Married”, or</p>
<pre><code class="language-php">echo $employeeMaritalStatus-&gt;value;
</code></pre>
<p>which gets you “Married/Civil Partner”;</p>
<p>The next thing you might want to do is convert a string to an enum value. Say if an API has returned a string value “Married”, you want to be able to convert that to a proper enum in your PHP object.</p>
<p>So we add a couple of static methods</p>
<pre><code class="language-php">enum MaritalStatus: string {
  case Single = 'Single';
  case Married = 'Married/Civil Partner';
  case Divorced = 'Divorced/Civil Partnership Dissolved';
  case Separated = 'Separated';
  case Widowed = 'Widowed/Surviving Civil Partner';

  public static function fromString(string $name): MaritalStatus {
    try {
      return self::{$name};
    } catch (\Error) {
      throw new \ValueError('"'.$name.'" is not a valid value for '.self::class);
    }
  }

  public static function fromNullableString(?string $name): ?MaritalStatus {
    return $name === null ? null : self::fromString($name);
  }
}
</code></pre>
<p>So now you can do</p>
<pre><code class="language-php">$myString = 'Married';
$employeeMaritalStatus = MaritalStatus::fromString($myString);
</code></pre>
<p>The next problem we need to solve is a problem I ran into when serializing objects containing the enum.</p>
<p>Say I've got a variable called <code>$employee</code> that contains a property <code>$maritalStatus</code> that I want to pass into an API</p>
<p>I do</p>
<pre><code class="language-php">$json = json_encode($employee);
</code></pre>
<p>to convert it to JSON to send to the API. If the marital status is “Single” or “Separated” it works, but if I send a “Married” one it falls over. The API complains that that’s not a valid MaritalStatus.</p>
<p>What’s happening is that by default, when you do json_encode on a backed enum, it converts it to the <em>string</em> value, not the enum value. So for a Single one, the API is receiving this</p>
<pre><code class="language-json">{
  "employeeId": 2645,
  "forename": "Jane",
  "surname": "Jones",
  "maritalStatus": "Single"
}
</code></pre>
<p>That’s fine because for a Single one, the enum and its string equivalent are identical, but for a Married one we’re sending</p>
<pre><code class="language-json">{
  "employeeId": 2645,
  "forename": "Jane",
  "surname": "Jones",
  "maritalStatus": "Married/Civil Partner"
}
</code></pre>
<p>The API doesn’t recognise “Married/Civil Partner” as a valid status.</p>
<p>So we have to control the serialisation behaviour ourselves. You implement the JsonSerializable interface.</p>
<pre><code class="language-php">enum MaritalStatus: string implements \JsonSerializable {
  case Single = 'Single';
  case Married = 'Married/Civil Partner';
  case Divorced = 'Divorced/Civil Partnership Dissolved';
  case Separated = 'Separated';
  case Widowed = 'Widowed/Surviving Civil Partner';

  public static function fromString(string $name): MaritalStatus {
    try {
      return self::{$name};
    } catch (\Error) {
      throw new \ValueError('"'.$name.'" is not a valid value for '.self::class);
    }
  }

  public static function fromNullableString(?string $name): ?MaritalStatus {
    return $name === null ? null : self::fromString($name);
  }

  public function jsonSerialize(): string {
    return $this-&gt;name;
  }
}
</code></pre>
<p>So now a Married one gets converted to JSON as “Married” instead of “Married/Civil Partner”. The API receives this</p>
<pre><code class="language-json">{
  "employeeId": 2645,
  "forename": "Jane",
  "surname": "Jones"
  "maritalStatus": "Married"
}
</code></pre>
<p>and it’s all happy.</p>
<p>Then to take it a step further. The <code>fromString()</code> and <code>fromNullableString()</code> both return a value of <code>MaritalStatus</code>, i.e. of the type that we’re currently in. Where that’s the case, you can have a return type of <code>self</code>, i.e.</p>
<pre><code class="language-php">enum MaritalStatus: string implements \JsonSerializable {
  case Single = 'Single';
  case Married = 'Married/Civil Partner';
  case Divorced = 'Divorced/Civil Partnership Dissolved';
  case Separated = 'Separated';
  case Widowed = 'Widowed/Surviving Civil Partner';

  public static function fromString(string $name): self {
    try {
      return self::{$name};
    } catch (\Error) {
      throw new \ValueError('"'.$name.'" is not a valid value for '.self::class);
    }
  }

  public static function fromNullableString(?string $name): ?self {
    return $name === null ? null : self::fromString($name);
  }

  public function jsonSerialize(): string {
    return $this-&gt;name;
  }
}
</code></pre>
<p>So now those three methods don’t have anything in them that refers to a specific enum type. They will work for <em>any</em> enum type. So you’d think that’s an obvious candidate for an abstract base class, but you can’t do inheritance on enums.</p>
<p>So there’s a thing called a <em>Trait</em> in PHP which I’d heard of but never actually looked into. It’s a bit like a quick and dirty base class. Or like one of those classes that’s got nothing but static methods, except the methods don’t have to be static.</p>
<pre><code class="language-php">trait Multiplying {
  public function multiplyBy2() {
    return $this-&gt;myVal * 2;
  }

  public function multiplyBy4() {
    return $this-&gt;myVal * 4;
  }
}
</code></pre>
<p>So once you’ve defined it, any class that uses that trait gets those methods.</p>
<pre><code class="language-php">class MyClass {
  use Multiplying;

  public int $myVal;
}

$myObject = new MyClass();
$myObject-&gt;myVal = 5;

echo $myObject-&gt;multiplyBy2();
echo '&lt;br&gt;';
echo $myObject-&gt;multiplyBy4();
</code></pre>
<p>That’s a rubbish example, but you get the idea.</p>
<p>So if we define a trait like this</p>
<pre><code class="language-php">trait CommonEnumMethods {
  public static function fromString(string $name): self {
    try {
      return self::{$name};
    } catch (\Error $e) {
      throw new \ValueError('"'.$name.'" is not a valid value for '.self::class);
    }
  }

  public static function fromNullableString(?string $name): ?self {
    return $name === null ? null : self::fromString($name);
  }

  public function jsonSerialize(): string {
    return $this-&gt;name;
  }
}
</code></pre>
<p>Our actual enum can look like this</p>
<pre><code class="language-php">enum MaritalStatus: string implements \JsonSerializable {
  use CommonEnumMethods;

  case Single = 'Single';
  case Married = 'Married/Civil Partner';
  case Divorced = 'Divorced/Civil Partnership Dissolved';
  case Separated = 'Separated';
  case Widowed = 'Widowed/Surviving Civil Partner';
}
</code></pre>
<p>And it gets all the methods from the trait. So now all new enums that we add can just use the trait to get all the functionality that we need.</p>
]]></content:encoded></item><item><title><![CDATA[Entity Framework Core]]></title><description><![CDATA[Extremely basic Getting Started with Entity Framework Core. If you've never used EF Core before you need to install the tools globally. Open the Visual…]]></description><link>https://pauls-brain-dump.hashnode.dev/entity-framework-core</link><guid isPermaLink="true">https://pauls-brain-dump.hashnode.dev/entity-framework-core</guid><category><![CDATA[dotnet]]></category><category><![CDATA[#entityframeworkcore]]></category><dc:creator><![CDATA[Paul Hunter]]></dc:creator><pubDate>Mon, 02 Nov 2026 13:24:05 GMT</pubDate><content:encoded><![CDATA[<p>Extremely basic Getting Started with Entity Framework Core.</p>
<p>If you've never used EF Core before you need to install the tools globally.</p>
<p>Open the Visual Studio Terminal window and do</p>
<pre><code class="language-powershell">dotnet tool install --global dotnet-ef
</code></pre>
<p>If you've already installed the tools but there has been an update in the meantime, you can bring them up to date by doing</p>
<pre><code class="language-powershell">dotnet tool update --global dotnet-ef
</code></pre>
<p>Your project needs a couple of NuGet packages</p>
<ul>
<li>Microsoft.EntityFrameworkCore.Design</li>
<li>Microsoft.EntityFrameworkCore.Sqlite</li>
</ul>
<p>(If you're using a different database then replace the SQLite package.)</p>
<p>You start off by defining some entity classes, e.g.</p>
<pre><code class="language-c#">public class Movie {
  public int Id { get; set; }
  public required string Title { get; set; }
  public int? ReleaseYear { get; set; }
}
</code></pre>
<p>Create a new class that inherits from DbContext</p>
<pre><code class="language-c#">public class MovieDatabaseDbContext : DbContext {
  public MovieDatabaseDbContext(DbContextOptions options) : base(options) { }
  public DbSet&lt;Movie&gt; Movies =&gt; Set&lt;Movie&gt;();
}
</code></pre>
<p>Register it in Program.cs</p>
<pre><code class="language-c#">builder.Services.AddDbContext(options =&gt;
  options.UseSqlite(builder.Configuration.GetConnectionString("Default")));
</code></pre>
<p>And add the connection string into appsettings.json</p>
<pre><code class="language-plaintext">"ConnectionStrings": { "Default": "Data Source=movies.db" }
</code></pre>
<p>Now we're going to create a <em>migration</em>. That word has always bamboozled me because to me, a migration is a big project where you're changing something important, like moving your application to a different framework or a different database. But in the context of EF Core, a <em>migration</em> is a set of instructions for creating or updating your database schema.</p>
<p>Open the Visual Studio Terminal window, navigate to the folder that contains the project that contains your DbContext class, and do</p>
<pre><code class="language-powershell">dotnet ef migrations add InitialCreate
</code></pre>
<p><em>InitialCreate</em> here can be anything you like. It's just a name that uniquely identifies this migration.</p>
<p>EF Core builds your project, and creates an instance of your DbContext class so that it can figure out what it needs to do to create the database.</p>
<p>If your DbContext isn't in an <a href="http://ASP.NET">ASP.NET</a> project (for example if you're putting your data access code in a separate class library), you need a slightly different command</p>
<pre><code class="language-powershell">dotnet ef migrations add InitialCreate --project MyDataAccessLib --startup-project MyWebApiProject
</code></pre>
<p>--project tells it where to look for the DbContext class</p>
<p>--startup-project tells it where to look for the code that instantiates the DbContext (in the Program.cs of your API project)</p>
<p>You can leave out --project and it'll look in the project folder that you're currently in.</p>
<p>If that completes successfully, you'll have a Migrations folder containing</p>
<ul>
<li>[timestamp]_InitialCreate.cs</li>
<li>[timestamp]_InitialCreate.Designer.cs</li>
<li>MovieDatabaseDbContextModelSnapshot.cs</li>
</ul>
<p>InitialCreate.cs is the migration code. It contains a method Up() to implement the changes in this migration, and a method Down() to reverse them.</p>
<p>You don't have to worry about InitialCreate.Designer.cs. That's just internal stuff that EF Core needs.</p>
<p>The snapshot is a snapshot of where the database should be when all the migrations have been applied.</p>
<p>To actually create the database, in the Terminal window, run</p>
<pre><code class="language-powershell">dotnet ef database update
</code></pre>
<p>This will create the database (movies.db) in the same folder as your project.</p>
]]></content:encoded></item></channel></rss>