<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ka2</title>
    <description>The latest articles on DEV Community by ka2 (@ka215).</description>
    <link>https://dev.to/ka215</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3040546%2F9b6c464a-7e03-49c3-a50d-3e09eda81f18.jpeg</url>
      <title>DEV Community: ka2</title>
      <link>https://dev.to/ka215</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ka215"/>
    <language>en</language>
    <item>
      <title>Automatically Generate OpenAPI 3.0 Schemas from Mock API Responses using PHP</title>
      <dc:creator>ka2</dc:creator>
      <pubDate>Fri, 11 Apr 2025 07:07:24 +0000</pubDate>
      <link>https://dev.to/ka215/automatically-generate-openapi-30-schemas-from-mock-api-responses-using-php-1emi</link>
      <guid>https://dev.to/ka215/automatically-generate-openapi-30-schemas-from-mock-api-responses-using-php-1emi</guid>
      <description>&lt;p&gt;If you've ever found yourself writing repetitive OpenAPI specs by hand, you'll love this.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What if your mock API server could &lt;strong&gt;auto-generate OpenAPI 3.0 schemas&lt;/strong&gt; just from example responses?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's exactly what &lt;a href="https://github.com/ka215/MockAPI-PHP" rel="noopener noreferrer"&gt;MockAPI-PHP&lt;/a&gt; does.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 What is MockAPI-PHP?
&lt;/h2&gt;

&lt;p&gt;MockAPI-PHP is a lightweight, file-based mock API server written in PHP 8.3+.&lt;br&gt;&lt;br&gt;
It lets you simulate RESTful API endpoints using just &lt;code&gt;.json&lt;/code&gt; or &lt;code&gt;.txt&lt;/code&gt; files — no backend or framework required.&lt;/p&gt;

&lt;p&gt;You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define dynamic responses using simple files&lt;/li&gt;
&lt;li&gt;Simulate polling, authentication, errors, and delays&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-generate OpenAPI 3.0 schemas&lt;/strong&gt; from your response examples&lt;/li&gt;
&lt;li&gt;Serve your mock API via browser or CLI — even integrate into CI/CD&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🚀 Key Features
&lt;/h2&gt;

&lt;p&gt;✅ JSON-based mock responses&lt;br&gt;&lt;br&gt;
✅ Dynamic parameters (&lt;code&gt;/users/{group}/{limit}&lt;/code&gt;)&lt;br&gt;&lt;br&gt;
✅ Response polling (per client)&lt;br&gt;&lt;br&gt;
✅ Built-in authentication (via &lt;code&gt;.env&lt;/code&gt;)&lt;br&gt;&lt;br&gt;
✅ Schema validation using &lt;code&gt;opis/json-schema&lt;/code&gt;&lt;br&gt;&lt;br&gt;
✅ Auto-generated OpenAPI files: YAML or JSON&lt;br&gt;&lt;br&gt;
✅ Simple CLI tool + PHP built-in server compatible&lt;/p&gt;


&lt;h2&gt;
  
  
  🧪 Example: Creating a Mock Endpoint
&lt;/h2&gt;

&lt;p&gt;Let's say you want to mock the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET /products&lt;/code&gt; → returns a list of products&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /products&lt;/code&gt; → accepts a new product object&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PUT /products&lt;/code&gt; → accepts a new product or already exists object&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PATCH /products/{id}&lt;/code&gt; → accepts a product property updates&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DELETE /products/{id}&lt;/code&gt; → accepts a product deletion&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /products?mock_response=error&lt;/code&gt; → returns an error response for get method&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /products?mock_response=error&lt;/code&gt; → returns an error response for post method&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PUT /products?mock_response=error&lt;/code&gt; → returns an error response for put method&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All you need to do is create this file structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;responses/
 └── products/
     ├── get/
     │     ├── default.json
     │     └── error.json
     ├── post/
     │     ├── default.json
     │     └── error.json
     ├── put/
     │     ├── default.json
     │     └── error.json
     ├── patch/
     │     └── default.json
     └── delete/
            └── default.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An example json file for get method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Product A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Description of Product A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;19.99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Electronics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"stock"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-04-01T12:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-04-01T12:00:00Z"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Product B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Description of Product B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;29.99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Books"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"stock"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-04-02T12:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"updated_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-04-02T12:00:00Z"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then start the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php start_server.php
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you're live on &lt;code&gt;http://localhost:3030/api/products&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the endpoint is a GET method, you can immediately check the response by accessing it directly in your browser.&lt;/p&gt;

&lt;p&gt;The best way to check the responses of the various methods is to send requests to the endpoints in the CLI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:3030/api/products
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"status"&lt;/span&gt;: &lt;span class="s2"&gt;"success"&lt;/span&gt;,
  &lt;span class="s2"&gt;"message"&lt;/span&gt;: &lt;span class="s2"&gt;"Product created successfully"&lt;/span&gt;,
  &lt;span class="s2"&gt;"data"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"id"&lt;/span&gt;: 1,
    &lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"Product Name"&lt;/span&gt;,
    &lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;"Product Description"&lt;/span&gt;,
    &lt;span class="s2"&gt;"price"&lt;/span&gt;: 19.99,
    &lt;span class="s2"&gt;"category"&lt;/span&gt;: &lt;span class="s2"&gt;"Category Name"&lt;/span&gt;,
    &lt;span class="s2"&gt;"stock"&lt;/span&gt;: 100,
    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;: &lt;span class="s2"&gt;"2025-04-01T12:00:00Z"&lt;/span&gt;,
    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;: &lt;span class="s2"&gt;"2025-04-01T12:00:00Z"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; PATCH http://localhost:3030/api/products/1
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"status"&lt;/span&gt;: &lt;span class="s2"&gt;"success"&lt;/span&gt;,
  &lt;span class="s2"&gt;"message"&lt;/span&gt;: &lt;span class="s2"&gt;"Product updated successfully"&lt;/span&gt;,
  &lt;span class="s2"&gt;"data"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"id"&lt;/span&gt;: 1,
    &lt;span class="s2"&gt;"name"&lt;/span&gt;: &lt;span class="s2"&gt;"Updated Product Name"&lt;/span&gt;,
    &lt;span class="s2"&gt;"description"&lt;/span&gt;: &lt;span class="s2"&gt;"Updated Product Description"&lt;/span&gt;,
    &lt;span class="s2"&gt;"price"&lt;/span&gt;: 19.99,
    &lt;span class="s2"&gt;"category"&lt;/span&gt;: &lt;span class="s2"&gt;"Updated Category Name"&lt;/span&gt;,
    &lt;span class="s2"&gt;"stock"&lt;/span&gt;: 100,
    &lt;span class="s2"&gt;"created_at"&lt;/span&gt;: &lt;span class="s2"&gt;"2025-04-10T12:00:00Z"&lt;/span&gt;,
    &lt;span class="s2"&gt;"updated_at"&lt;/span&gt;: &lt;span class="s2"&gt;"2025-04-10T12:00:00Z"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; DELETE http://localhost:3030/api/products/1
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"code"&lt;/span&gt;: 204,
  &lt;span class="s2"&gt;"message"&lt;/span&gt;: &lt;span class="s2"&gt;"No Content"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📘 Bonus: Auto-Generate OpenAPI 3.0 Schema
&lt;/h2&gt;

&lt;p&gt;Want to generate an OpenAPI spec file based on your current mock responses?&lt;/p&gt;

&lt;p&gt;Just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php generate-schema.php yaml &lt;span class="s2"&gt;"My Awesome API"&lt;/span&gt; &lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll get a schema/openapi.yaml file, ready to import into Swagger, Stoplight, or Postman.&lt;/p&gt;

&lt;p&gt;It even embeds trimmed example data from your mock files.&lt;/p&gt;

&lt;p&gt;If you preview the OpenAPI Schema file automatically generated from the response configuration in the previous section with SwaggerUI, it will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8baxw6cq73mlh4qavccv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8baxw6cq73mlh4qavccv.png" alt="SwaggerUI Preview" width="800" height="1040"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conveniently, arrays in the JSON file registered as dummy responses are optimized as examples by trimming them to only the first element, which prevents the schema file from becoming too large.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠 Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;API-first design: mock first, develop later&lt;/li&gt;
&lt;li&gt;Frontend integration without waiting for backend&lt;/li&gt;
&lt;li&gt;Testing various response types (success, error, timeout, etc.)&lt;/li&gt;
&lt;li&gt;Validating schema structure for contract testing&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧩 Try It Now
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/ka215/MockAPI-PHP" rel="noopener noreferrer"&gt;https://github.com/ka215/MockAPI-PHP&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Requirements: PHP 8.3+, Composer&lt;/li&gt;
&lt;li&gt;License: MIT&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Thanks for reading! 🙌&lt;br&gt;
If you find this tool useful, feel free to give it a ⭐️ on GitHub or share with your team.&lt;/p&gt;

</description>
      <category>php</category>
      <category>openapi</category>
      <category>mockapi</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
