<?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: Tumusiime Ezra Jnr</title>
    <description>The latest articles on DEV Community by Tumusiime Ezra Jnr (@jet_ezra).</description>
    <link>https://dev.to/jet_ezra</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%2F267907%2F893fc27e-b069-4a44-a86c-4b8e5ca41298.jpg</url>
      <title>DEV Community: Tumusiime Ezra Jnr</title>
      <link>https://dev.to/jet_ezra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jet_ezra"/>
    <language>en</language>
    <item>
      <title>💥Pionia framework🚀 - initially a "hobby project"!</title>
      <dc:creator>Tumusiime Ezra Jnr</dc:creator>
      <pubDate>Fri, 26 Jul 2024 07:28:40 +0000</pubDate>
      <link>https://dev.to/jet_ezra/pionia-initially-a-hobby-project-5bmc</link>
      <guid>https://dev.to/jet_ezra/pionia-initially-a-hobby-project-5bmc</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Pionia framework started as my hobby project, but now, I really can't tell where its roads are leading!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I started Pionia to just challenge the status quo. I saw that some things are just made in the name of "standardisation" yet we don't need them.&lt;/p&gt;

&lt;p&gt;Now Pionia is one of my favourite frameworks and I intend to put everything I would wish for a cool framework to have.&lt;/p&gt;

&lt;p&gt;On its official docs, I defined its road map and how far it still has to go. Whereas I may be slow in achieving all the features defined, someday, all of them will be achieved. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In the start, I used to post articles comparing Pionia with most PHP frameworks, but that was all wrong! Pionia shouldn't be compared with any since its pattern - moonlight is like no other! Well, some say Moonlight is close to GraphQL, which I don't deny by the way, but it's a bit better!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That said, the following targets have already been achieved!&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Fully customisable security in terms of authentication and authorisation.&lt;/strong&gt; Pionia approaches RBAC the same way Spring Boot does while borrowing the concept of authentication backends from Django. Our authentication backends work in a chain format, when one authenticates the user into our context, we break the chain and ignore the rest! This implies you can create an authentication backend for your mobile app different from the one of your Web apps, it's that cool!&lt;br&gt;
Authentication and authorisation is done on the service level or action level.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember, services in Pionia are just PHP classes that group together related business logic(actions) e.g. &lt;code&gt;AuthService&lt;/code&gt; and actions are just php class methods that perform a single unit of work such as &lt;code&gt;login&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;👉 &lt;strong&gt;Fully customised database management.&lt;/strong&gt; &lt;br&gt;
Pionia, like Spring Boot and other cool frameworks of Yii and Express, can be used with 0 Models(no model layer), but unlike these frameworks, there is even no support for that layer at all. Whereas a few somehow "lazy" 😒 developers will claim that this is a bad😠 approach, but it's the best part. Most frameworks become slow while hydrating query results into model classes, especially in instances of selecting multiple records, &lt;em&gt;Pionia will never face that&lt;/em&gt;. It won't even need to cache queries, because the only reason why queries are cached is to avoid model hydration as much as possible! Pionia comes shipped up with Porm(which is also maintained by the same team) that will enable you to perform all queries you need even complex ones without breaking a sweat. Pionia has also inbuilt mechanisms to query multiple databases at ago and also paginate your data smoothly!&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;This one comes from a common saying, "Too many cooks, spoil the soup".&lt;/strong&gt; Pionia believes the term controller has been misused. There should always be just one controller - looking at your project as if it's a car, you can't have multiple steering wheels! So, the only controller in Pionia, you as an end developer won't even interact with it since it's just one and Pionia decided to take care of it! This also implies that we have a single endpoint(well, this is also per API version). &lt;br&gt;
Now, I would like you to take a moment and imagine your Laravel code, doing the exact staff, but with no controllers, no models, no routes(different approach for this too), Just one switch(Pionia-specific concept) for your entire API version and one endpoint!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;routes.php&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$router&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PioniaRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$router&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addSwitchFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"\app\switches\V1Switch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"v1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addSwitchFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"\app\switches\V2Switch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"v2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addSwitchFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"\app\switches\V3Switch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"v2"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;switches/V1Switch&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;V1Switch&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseApiServiceSwitch&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @inheritDoc
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;registerServices&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'service1'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ServiceOne&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="s1"&gt;'service2'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ServiceTwo&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 &lt;strong&gt;Developer Performance matters✊️✊️&lt;/strong&gt;. I believe developers should be able to roll out an API in just hours or minutes, Pionia believes too! This is a concept that is very common in Django Rest Framework using their generic views. Pionia also ships in Generic Services. These specifically help you to &lt;code&gt;create&lt;/code&gt;(with uploads in mind), &lt;code&gt;delete&lt;/code&gt;, &lt;code&gt;retrieve/details&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, and &lt;code&gt;list&lt;/code&gt;(paginated) without even writing 10 lines of code. These also work well with relationships(without models btw). Every time I have tried to pull off an API, these have always been my go-to. They also support full customization using hooks. Every action can be customised by you! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pionia tends to make php development that easy just as we already see in frameworks like Rails and Django.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Developers also usually face the problem of a huge, growing and hard-to-inherit codebase. Pionia solved this too. This is solved by the concept of services, the only part of Pionia that Developers will always play with, while Pionia takes care of the rest of the other parts!&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;The middleware concept is great.&lt;/strong&gt; Pionia believes that Developers should find it easy to intercept every request and response, and do some logic or checks.&lt;br&gt;
So, we support middlewares too! But how we write them, is surprisingly simpler, unlike most frameworks, well, we don't approach the same way in the first place, so we can't boot them on the routes(which was usually confusing to many devs), here, these are just classes in the &lt;code&gt;middlewares&lt;/code&gt; folder, registered in our "settings.ini" under the &lt;code&gt;middlewares&lt;/code&gt; section. And that's it! You can now maybe encrypt and decrypt all your requests before they even hit your authentication backends or do anything you wish, anything, anything on both the request and response!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[middleware]&lt;/span&gt;
&lt;span class="c"&gt;; you middleware here
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 Frontend integration should be easy, for crying 😢 😭 out loud!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Whatever is happening in the current front end these days is strange! SPA were supposed to be a good deal! The problem came when Developers wanted to write Frontend logic on the backend! Am one of those few nerds who believe Javascript should never be written on the server no matter the performance gains, it's not worth the consequences!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A library called &lt;code&gt;jet-fetch&lt;/code&gt; which is a simple wrapper on top of our normal and elegant &lt;code&gt;fetch&lt;/code&gt; API, has been put forward but majorly with one unique feature on top of having JWT authentication in mind, querying moonlight backends. Pionia is one of them, so using this library, just write your normal Vue, react, angular and query your backend well. &lt;br&gt;
Developers who overused server-side rendering have also struggled when it came to integration with multiple frontend architectures in the same API, like serving your mobile, web and electron apps with the same API.&lt;br&gt;
So, Pionia believes Frontend should stay that way, and the back end should stay in its lane too!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Just because you can doesn't usually mean you should!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pionia is also putting measures to serve your front end by your backend in production. This means, that after completing your frontend, you build it, drop it in a certain folder in your backend, and then you just host your backend!&lt;/p&gt;

&lt;p&gt;This is already seen in Spring Boot Java; yes, it's coming to PHP.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;API versioning can be done better.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;In Pionia, we believe that API endpoints should be something like "&lt;a href="https://mydomain.com/api/version/" rel="noopener noreferrer"&gt;https://mydomain.com/api/version/&lt;/a&gt;", and that should be just one in your entire app. This implies that version one can be &lt;code&gt;/api/v1/&lt;/code&gt; and version two can be &lt;code&gt;/api/v2/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is exactly what Pionia does. In our &lt;code&gt;routes.php&lt;/code&gt; you will find a method called &lt;code&gt;addSwitchFor&lt;/code&gt; which determines the switch class we are pointing to and its version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Core\Routing\PioniaRouter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$router&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PioniaRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$router&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addSwitchFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"\app\switches\V1Switch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"v1"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above tells Pionia that all traffic coming through &lt;code&gt;/api/v1/&lt;/code&gt; should be routed to the MainSwitch.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Look at &lt;code&gt;switches&lt;/code&gt; as your normal home electricity switches, all those electronics connected to that switch are flipped whenever the switch is flipped. Turning the switch off cuts current from all the connected electronics and the reverse. The same as in Pionia, only those services registered in the given switch are managed and considered when that switch is called. Here, calling the switch is like flipping it to one state.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This implies, that to roll out a new API version, you only need to register a new switch and register it in the routes with the version that shall reference it. Also, this implies that the entire service can be registered in multiple switches! The frontend team only changes the version on their base URL, how cool 😎 😀 is that! If you're using &lt;code&gt;jet-fetch&lt;/code&gt; this is &lt;a href="https://github.com/OSCA-Kampala-Chapter/jet-fetch?tab=readme-ov-file#moonlight-pattern-developers" rel="noopener noreferrer"&gt;already taken care of for you!&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Jet&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jet-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rocket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Jet&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:8000/api/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;rocket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;moonlightRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yourService&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yourAction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;anyOtherData&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;v2/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can spend the entire day trying to discuss all the special features of Pionia and the entire moonlight ✨️ pattern, but if you have noticed all the mentioned features, they are concepts that have so far gone wrong with our current backend development especially when it comes to API Development.&lt;/p&gt;

&lt;p&gt;If there is anything you would wish for Pionia(Moonlight) to address, anything you feel has already gone in a weird direction, please mention it in the comment section below. &lt;/p&gt;

&lt;p&gt;If you're looking for the docs of Pionia, which are only 40% complete(🫨🫨), &lt;a href="https://pionia.netlify.app" rel="noopener noreferrer"&gt;you can find them here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/phppionia?t=HUF5UsyTw4XaOFktA2757g&amp;amp;s=09" rel="noopener noreferrer"&gt;You can also join us on X and share with us your experience&lt;/a&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>api</category>
      <category>backend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Another framework, Arrrgggg!!!</title>
      <dc:creator>Tumusiime Ezra Jnr</dc:creator>
      <pubDate>Wed, 10 Jul 2024 07:07:46 +0000</pubDate>
      <link>https://dev.to/jet_ezra/another-framework-arrrgggg-5ain</link>
      <guid>https://dev.to/jet_ezra/another-framework-arrrgggg-5ain</guid>
      <description>&lt;p&gt;&lt;strong&gt;Another PHP framework? Arrrgggg!!! More like, why not?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pionia framework has the answer for this. Pionia trims off the unnecessary concerns of developing apis and you stay focused on only your business logic.&lt;/p&gt;

&lt;p&gt;It also somehow meets both configuration and conventions in the midway. &lt;/p&gt;

&lt;p&gt;Imagine scenarios where an api is done with in 20 mins, well, in python and Ruby that's not an imagination, but in php it was, but not anymore.&lt;/p&gt;

&lt;p&gt;Frameworks like laravel are really good for fullstack applications and they shine that way. But if you intend to only pull off an API that will be easy to integrate with your frontend, then Pionia is your answer. &lt;/p&gt;

&lt;p&gt;Why so?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Single request format.&lt;br&gt;
The server won't have to keep switching protocols to watch your requests. Everything is POST and with the $data key in your actions, all your request data is there. You pick what you want, or mark required the data you need.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Single Response format whether on failure or success! Really? Is that even nice? You may ask!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yes it is, this is how. We introduce the concept of returnCodes for Status Codes. We maintain the same Status code 200 OK for all the requests that hit the application server, and as you already know, when a request returns 200 OK, tools like axios give you access to the returned data, now in the returned data, you get to set your own returnCode, you can maintain the existing http codes but you're also open now to even define your custom ones.&lt;/p&gt;

&lt;p&gt;Thus the frontend does not need to read errors from the catch block of your http, but in the same try block, everything is there!&lt;/p&gt;

&lt;p&gt;Now, I don't know if it was only me, but reading errors in axios was not my favorite part, but now, with Pionia, it is because it's not any different!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As you see the first two points, they have a new advantage they introduce, the fact that both the request and response are the same throughout, then it means one endpoint is enough for an entire app! Now, this is not an innovation, it's just an implementation. We have already seen API Gateways and Graphql tending to this path, and how about a framework that has it as the default behaviour. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After implementing this, we didn't need routes and controllers in Pionia, but also a new concept of Switches was introduced. Switches read the service and action defined in the request and point the entire traffic directly to that service(php class) and action(class method).&lt;/p&gt;

&lt;p&gt;This is great, it implies that in your app, your entire logic has reduced to just your services. So like that, we have achieved developer performance since you focus on only services not forgetting maintainability too! Your code is easy to inherit since even the new dev will only have to look at services.&lt;/p&gt;

&lt;p&gt;Generics in Pionia are another concept to get you started in seconds. These, if well used, can even reduce your time to pull off an API from minutes to even seconds. &lt;/p&gt;

&lt;p&gt;Battle-tested components. We also believe that if something is working well, then don't reinvent it. That's why Pionia at it's core stands on the shoulders of giants like symfony and Nette. Our code generators are powered by Nette, our tests are powered by phpunit, our logs are powered by Monolog, our request sanitisation mechanisms are powered by symfony. This implies that most of the components working in Pionia are battle-tested to work with complex projects without breaking a sweat😓 &lt;/p&gt;

&lt;p&gt;Pionia also does more than this, it gives us a new approach to look at RBAC in php which is inspired by the combination of spring boot and django bytheway. This includes use of authentication backends that will set the ContextUserObject. So, no matter what you want to use, you're totally free! As long as you set the context user object. The framework being fully restful also expects your authentication to be stateless or sessionless. So anything you have in mind should work with Pionia framework!&lt;/p&gt;

&lt;p&gt;Middlewares are still here. That means you get perform great staff like request sanitisation, encryption and decryption using our Middlewares!!&lt;/p&gt;

&lt;p&gt;On program performance in abit, Pionia removes the model layer! Whyyyyyy?? Another great thing gone!! Damn framework!!! You may say! &lt;/p&gt;

&lt;p&gt;But Rest applications are meant to return json data. This can be an array or object. Php as php knows both datatypes and gives you various ways to interact with them. So, when you query your database and get back your results, they are in one of the above formats. This is the normal underlying PDO. However, when you have models, then you do something called model hydration. This is where the above arrays and objects are mapped to a certain class. With objects, this might not be a big problem, but with arrays of objects, this is really expensive! &lt;/p&gt;

&lt;p&gt;So, Pionia also knows that you need to easily query your database well, so, it has a tool called Porm. Porm can help you query any database supported by PDO and return the results in the format that is ready for exposure as an API.&lt;/p&gt;

&lt;p&gt;This also has another added advantage. It implies Porm can work with all your already existing databases. We believe backend developers should focus on that and database engineers should focus on that! And yet, with this QueryBuilder, backend engineers can query any database whether new or existing and to make it more fun, multiple databases at a time!!&lt;/p&gt;

&lt;p&gt;This should be just words, head over to &lt;a href="https://pionia.netlify.app" rel="noopener noreferrer"&gt;https://pionia.netlify.app&lt;/a&gt; and see for yourself.&lt;/p&gt;

&lt;p&gt;We welcome all contributions, criticisms  sponsorship as that's how we shall grow!! &lt;/p&gt;

&lt;p&gt;Have fun 😁 &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>pionia</category>
      <category>php</category>
      <category>restapi</category>
    </item>
    <item>
      <title>Getting started with Pionia Framework</title>
      <dc:creator>Tumusiime Ezra Jnr</dc:creator>
      <pubDate>Sat, 06 Jul 2024 19:30:29 +0000</pubDate>
      <link>https://dev.to/jet_ezra/getting-started-with-pionia-frameowrk-54lo</link>
      <guid>https://dev.to/jet_ezra/getting-started-with-pionia-frameowrk-54lo</guid>
      <description>&lt;p&gt;For this specific article, I will save you from the backgrounds and inspirations of the framework. You can always find those in the &lt;a href="https://pionia.netlify.app" rel="noopener noreferrer"&gt;official framework documentation here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, let's get to work and draft a simple API in less than 20 minutes.&lt;/p&gt;

&lt;p&gt;The following sections assume you're running PHP 8.1+, the composer is already set up and you have any RDBMS database preferably one of MySQL and Postgres.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we shall be working on today.
&lt;/h2&gt;

&lt;p&gt;We shall create an API that:-&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Creates a todo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deletes a todo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Marks a todo as complete&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Queries completed todos&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Queries 1 or more random incomplete todo[s]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Returns a list of all todos&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Returns a list of paginated todos&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Updates a todo&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Returns a single todo items&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Returns overdue todos&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This sounds and looks simple, but by the end of the day, you shall be able to perform all CRUD operations in Pionia, data filtration and interacting with Pionia APIs.&lt;/p&gt;

&lt;p&gt;Our project shall be called todoApp.&lt;/p&gt;

&lt;p&gt;For starters, we shall need to bootstrap a Pionia project using the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project pionia/pionia-app todoApp    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On successful installation, you should have a directory &lt;a href="https://pionia.netlify.app/documentation/application-structure/" rel="noopener noreferrer"&gt;similar to this&lt;/a&gt; though missing a few folders. Our focus folder is &lt;strong&gt;app/services.&lt;/strong&gt; Other folders can be added when needed especially using our &lt;code&gt;pionia&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Pionia does not use models, therefore, it can work with only existing databases. For starters, you need to create your database, whether in Postgres, SQLite, MySQL, or any other database supported by PHP PDO.&lt;/p&gt;

&lt;p&gt;For this guide, we shall use MySQL and create a database called &lt;code&gt;todo_app_db&lt;/code&gt; . In your &lt;code&gt;mysql&lt;/code&gt; console run the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;todo_app_db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="n"&gt;todo_app_db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, let's add the table that we shall be working with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;todo&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;          &lt;span class="nb"&gt;bigint&lt;/span&gt; &lt;span class="n"&gt;auto_increment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;       &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;225&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                        &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;                                &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt;  &lt;span class="nb"&gt;timestamp&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;start_date&lt;/span&gt;  &lt;span class="nb"&gt;date&lt;/span&gt;                                &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;end_date&lt;/span&gt;    &lt;span class="nb"&gt;date&lt;/span&gt;                                &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;completed&lt;/span&gt;   &lt;span class="nb"&gt;bool&lt;/span&gt;      &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;             &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;constraint&lt;/span&gt; &lt;span class="n"&gt;table_name_pk&lt;/span&gt;
        &lt;span class="k"&gt;primary&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is all outside the Pionia framework. Let's come back to Pionia now.&lt;/p&gt;

&lt;p&gt;We already have our default switch targeting &lt;code&gt;/api/v1/&lt;/code&gt; registered already. This can be viewed in the &lt;code&gt;routes.php&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Core\Routing\PioniaRouter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PioniaRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$router&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addSwitchFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"application\switches\MainApiSwitch"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$router&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getRoutes&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if we look at &lt;code&gt;application\switches\MainApiSwitch&lt;/code&gt;, we find it is registering the &lt;code&gt;UserService&lt;/code&gt;. Let's drop that and create our service. Remember to remove the import too - &lt;code&gt;use application\services\UserService;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;registerServices&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'user'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// remove this&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it should be looking like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;registerServices&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;

        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Head over to &lt;code&gt;services&lt;/code&gt; folder and remove the &lt;code&gt;UserService&lt;/code&gt; too. We want to add our own.&lt;/p&gt;

&lt;p&gt;In your terminal, run the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; php pionia addservice todo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shall create our new service &lt;code&gt;TodoService&lt;/code&gt; in the services folder looking like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * This service is auto-generated from pionia cli.
 * Remember to register your this service as TodoService in your service switch.
 */&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;application\services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Request\BaseRestService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Response\BaseResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseRestService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * In the request object, you can hit this service using - {'ACTION': 'getTodo', 'SERVICE':'TodoService' ...otherData}
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$files&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'You have reached get action'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="cd"&gt;/**
     * In the request object, you can hit this service using - {'ACTION': 'createTodo', 'SERVICE':'TodoService' ...otherData}
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;createTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$files&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'You have reached create action'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="cd"&gt;/**
     * In the request object, you can hit this service using - {'ACTION': 'listTodo', 'SERVICE':'TodoService' ...otherData}
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;listTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$files&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'You have reached list action'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="cd"&gt;/**
     * In the request object, you can hit this service using - {'ACTION': 'deleteTodo', 'SERVICE':'TodoService' ...otherData}
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;deleteTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$files&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'You have reached delete action'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before doing anything else, let's first register our service in the &lt;code&gt;MainApiSwitch&lt;/code&gt; in our services under &lt;code&gt;registerServices&lt;/code&gt; like this.&lt;/p&gt;

&lt;p&gt;Also, since we don't intend to upload anything, let's remove all &lt;code&gt;?array $files&lt;/code&gt; from our actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;registerServices&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'todo'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TodoService&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, let's test what we have so far. Run the server using the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;php&lt;/span&gt; &lt;span class="n"&gt;pionia&lt;/span&gt; &lt;span class="n"&gt;serve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your app is being served under &lt;code&gt;http://localhost:8000&lt;/code&gt; but your API is served under &lt;code&gt;/api/v1/&lt;/code&gt; . Let's first open &lt;code&gt;http://localhost:8000&lt;/code&gt;, you should see the following.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykw9basdsq9szc2ryo4n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykw9basdsq9szc2ryo4n.png" alt="New Pionia API landing page" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's try to open &lt;code&gt;http://localhost:8000/api/v1&lt;/code&gt; in browser. If you have JSONViewer installed, you should see this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfr9t7uzb60zd4gwokaj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfr9t7uzb60zd4gwokaj.png" alt="Pionia API status check via get request" width="800" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All &lt;code&gt;get&lt;/code&gt; requests in Pionia will return the above! Therefore to test our service we need to make POST requests, we might not pull that off in the browser, so, I suggest we use Postman.&lt;/p&gt;

&lt;p&gt;Fire up your postman or whatever you want to use. I will use Postman. All our services can receive either JSON or form data. Form data should be preferred for file uploads.&lt;/p&gt;

&lt;p&gt;For now, let's send JSON data.&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="nl"&gt;"SERVICE"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ACTION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"getTodo"&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;And we should get back the following.&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="nl"&gt;"returnCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"returnMessage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You have reached get action"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"returnData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"extraData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&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;This is what we are returning in our &lt;code&gt;getTodo&lt;/code&gt;:-&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'You have reached get action'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More about how we discovered the right action can be found &lt;a href="https://pionia.netlify.app/documentation/services/" rel="noopener noreferrer"&gt;here in the official docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's add our database settings in our &lt;code&gt;settings.ini&lt;/code&gt; file like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[db]&lt;/span&gt;
&lt;span class="c"&gt;;change this to your db name
&lt;/span&gt;&lt;span class="py"&gt;database&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"todo_app_db"&lt;/span&gt;
&lt;span class="c"&gt;;change this to your db username
&lt;/span&gt;&lt;span class="py"&gt;username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"root"&lt;/span&gt;
&lt;span class="py"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"mysql"&lt;/span&gt;
&lt;span class="py"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;
&lt;span class="py"&gt;password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="py"&gt;port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;3306&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see what is happening in real time, Pionia ships in with a logger, open a new terminal window and run the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="err"&gt;tail&lt;/span&gt; &lt;span class="err"&gt;-f&lt;/span&gt; &lt;span class="err"&gt;server.log&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also edit the logging behaviour in the settings file as below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[SERVER]&lt;/span&gt;
&lt;span class="py"&gt;port&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;8000&lt;/span&gt;
&lt;span class="py"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;LOG_REQUESTS&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;8000&lt;/span&gt;
&lt;span class="py"&gt;LOG_DESTINATION&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;server.log ; the file to log to.&lt;/span&gt;
&lt;span class="py"&gt;NOT_FOUND_CODE&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;404&lt;/span&gt;
&lt;span class="py"&gt;UNAUTHENTICATED_CODE&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;401&lt;/span&gt;
&lt;span class="py"&gt;SERVER_ERROR_CODE&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;500&lt;/span&gt;
&lt;span class="py"&gt;HIDE_IN_LOGS&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="c"&gt;; what fields should be encrypted in logs
&lt;/span&gt;&lt;span class="s"&gt;HIDE_SUB= ; the string to replace with the hidde value default is ********&lt;/span&gt;
&lt;span class="py"&gt;LOGGED_SETTINGS&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="c"&gt;; the settings to add in logs eg db,SERVER
&lt;/span&gt;&lt;span class="s"&gt;LOG_FORMAT=TEXT ; can be json or test&lt;/span&gt;
&lt;span class="c"&gt;;APP_NAME= ; you can override this as the app name. default is Pionia.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After setting this up, you be able to now view all requests and responses in your terminal.&lt;/p&gt;

&lt;p&gt;So far we have not yet started coding anything. Just adding optional configurations to our app.&lt;/p&gt;

&lt;p&gt;Let's start by creating a todo in our &lt;code&gt;createTodo&lt;/code&gt; action.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;createTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'start_date'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'end_date'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;$description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;$startDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'Y-m-d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;strtotime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'start_date'&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
        &lt;span class="nv"&gt;$endDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'Y-m-d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;strtotime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'end_date'&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;


        &lt;span class="nv"&gt;$saved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'start_date'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$startDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'end_date'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$endDate&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'You have successfully created a new todo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;$saved&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then let's send our request to target this action with all the required data like this.&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="nl"&gt;"SERVICE"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ACTION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"createTodo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Am a brand new todo"&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="s2"&gt;"Am the description of the brand new todo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"12/12/2024"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"end_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"06/06/2024"&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;And we shall get back our response like this.&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="nl"&gt;"returnCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"returnMessage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You have successfully created a new todo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"returnData"&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;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Am a brand new todo"&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;"Am the description of the brand new todo"&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;"2024-07-06 22:23:47"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"start_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2024-12-12"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"end_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2024-06-06"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"completed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&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;"extraData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&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;To shed some light on what is going on. The client requested &lt;code&gt;/api/v1/&lt;/code&gt;, in the request, the client defined the &lt;code&gt;SERVICE&lt;/code&gt; it is targeting, and the &lt;code&gt;ACTION&lt;/code&gt;. This came straight to our &lt;code&gt;index.php&lt;/code&gt; which also calls the kernel and sends all these requests to it.&lt;/p&gt;

&lt;p&gt;The kernel sanitises the request and checks if there is an endpoint that handles &lt;code&gt;/api/v1&lt;/code&gt;, it then sends the entire sanitised request to the switch in our case, the &lt;code&gt;MainApiSwich&lt;/code&gt;, this in turn checks if it has any &lt;code&gt;service&lt;/code&gt; that matches the &lt;code&gt;SERVICE&lt;/code&gt; name that came through our request. It discovered that there is and it is called &lt;code&gt;TodoService&lt;/code&gt;. It loads this service and calls the method that matches the name of the &lt;code&gt;ACTION&lt;/code&gt; key, passing along all the request data as &lt;code&gt;$data&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The action also expects certain data to be available in the request. This can be observed on this line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'start_date'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'end_date'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If any of the required data is not found on the request. The request will abort with a clean exception. Let's test this.&lt;/p&gt;

&lt;p&gt;In your postman, delete the &lt;code&gt;title&lt;/code&gt; key and send it as follows:-&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="nl"&gt;"SERVICE"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ACTION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"createTodo"&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="s2"&gt;"Am the description of the brand new todo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"12/12/2024"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"end_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"06/06/2024"&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;This will fail like below:-&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="nl"&gt;"returnCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"returnMessage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The field title is required"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"returnData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"extraData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&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;Notice that all scenarios still return an HTTP Status Code of 200 OK, but different returnCode[s]. Also, notice that the response format stays the same throughout. This is &lt;a href="https://pionia.netlify.app/moonlight/introduction-to-moonlight-architecture/" rel="noopener noreferrer"&gt;moonlight pattern&lt;/a&gt; in action!&lt;/p&gt;

&lt;p&gt;This is how you can pull off actions in Pionia. However, Pionia suggests that if what you are looking for is just CRUD, then you can look into &lt;a href="https://pionia.netlify.app/documentation/generic-services/" rel="noopener noreferrer"&gt;Generic Services&lt;/a&gt;. If you do not know about generic services, you can read about these in &lt;a href="https://hashnode.com/post/cly9sd3zk000f09l6cy3qdjbj" rel="noopener noreferrer"&gt;one of my articles here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, proceeding, let's first create the entire CRUD and see what generic services can help us reduce.&lt;/p&gt;

&lt;p&gt;Full-Service code so far for our &lt;code&gt;TodoService&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="cd"&gt;/**
 * This service is auto-generated from pionia cli.
 * Remember to register this service as TodoService in your service switch.
 */&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;application\services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Exceptions\FailedRequiredException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Request\BaseRestService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Request\PaginationCore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Response\BaseResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Porm\database\aggregation\Agg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Porm\database\builders\Where&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Porm\exceptions\BaseDatabaseException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Porm\Porm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseRestService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * In the request object, you can hit this service using - {'ACTION': 'getTodo', 'SERVICE':'TodoService' ...otherData}
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;$todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$todo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="cd"&gt;/**
     * In the request object, you can hit this service using - {'ACTION': 'createTodo', 'SERVICE':'TodoService' ...otherData}
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;createTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'start_date'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'end_date'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;$description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;$startDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'Y-m-d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;strtotime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'start_date'&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
        &lt;span class="nv"&gt;$endDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'Y-m-d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;strtotime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'end_date'&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;


        &lt;span class="nv"&gt;$saved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'start_date'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$startDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'end_date'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$endDate&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'You have successfully created a new todo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="nv"&gt;$saved&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="cd"&gt;/**
     * In the request object, you can hit this service using - {'ACTION': 'listTodo', 'SERVICE':'TodoService' ...otherData}
     * @throws BaseDatabaseException
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;listTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$todos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;


    &lt;span class="cd"&gt;/**
     * In the request object, you can hit this service using - {'ACTION': 'deleteTodo', 'SERVICE':'TodoService' ...otherData}
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;deleteTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'To-do deleted successfully'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * In the request object, you can hit this service using - {'ACTION': 'deleteTodo', 'SERVICE':'TodoService' ...otherData}
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;updateTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;$todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Todo with id &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt; not found"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nv"&gt;$todo&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nv"&gt;$todo&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$startDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'start_date'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'Y-m-d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;strtotime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'start_date'&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$todo&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;start_date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$endDate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'end_date'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'Y-m-d'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;strtotime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'end_date'&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$todo&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;end_date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$completed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'completed'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nv"&gt;$todo&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'start_date'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$startDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'end_date'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$endDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'completed'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$completed&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$newTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'To-do updated successfully'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$newTodo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @param $data
     * @return BaseResponse
     * @throws BaseDatabaseException
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;randomTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'size'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$todos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @param $data
     * @return BaseResponse
     * @throws BaseDatabaseException
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;markComplete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="nv"&gt;$todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Todo with id &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt; not found"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$todo&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Todo with id &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt; is already completed"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'completed'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$newTodo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'To-do marked as completed'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$newTodo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @throws BaseDatabaseException
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;listCompletedTodos&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'completed'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$todos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @throws BaseDatabaseException
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;listPaginatedTodos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'limit'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'offset'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nv"&gt;$paginator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PaginationCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$offset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$paginator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;paginate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$todos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * @throws BaseDatabaseException
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;listOverdueTodos&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$today&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Y-m-d'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="nc"&gt;Where&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;and&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="s2"&gt;"end_date[&amp;lt;]"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$today&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s1"&gt;'completed'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
            &lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$todos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above, we have completed our entire checklist of all we needed to cover. Play with it in Postman to see if everything is functioning properly.&lt;/p&gt;

&lt;p&gt;As you have noticed it, we only focused on services, nothing like controllers, routes, models!! This is how Pionia is changing how we develop APIs.&lt;/p&gt;

&lt;p&gt;Let me know what you say about this framework in the comment section below.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>pionia</category>
      <category>restapi</category>
      <category>php</category>
    </item>
    <item>
      <title>The Ultimate Guide to Pionia Generic Services.</title>
      <dc:creator>Tumusiime Ezra Jnr</dc:creator>
      <pubDate>Sat, 06 Jul 2024 06:56:04 +0000</pubDate>
      <link>https://dev.to/jet_ezra/the-ultimate-guide-to-pionia-generic-services-id</link>
      <guid>https://dev.to/jet_ezra/the-ultimate-guide-to-pionia-generic-services-id</guid>
      <description>&lt;p&gt;&lt;a href="https://pionia.netlify.app/" rel="noopener noreferrer"&gt;Pionia framework&lt;/a&gt; is a PHP Rest framework that is changing how we used to develop Rest platforms. Unlike all the existing frameworks, it gives the entire process a whole new look, making the development of APIs much simpler and less boring. This is because it runs on a different and rather 'new' pattern called &lt;code&gt;moonlight&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Per se, moonlight is not a new architecture/pattern, most institutions/companies/developers have been using it but just unnamed. But today, we aren't talking about moonlight, you can &lt;a href="https://dev.to/jet_ezra/moonlight-architecture-the-old-new-4ph5"&gt;read about it in my other article here&lt;/a&gt; and even leave your comments.&lt;/p&gt;

&lt;p&gt;To bootstrap a new Pionia project, you need to run the following command assuming you already have composer set up.&lt;/p&gt;

&lt;p&gt;Let's create a todo_app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer create-project pionia/pionia-app todo_app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also run the same project using the pionia command like below:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;To watch you logs as they happen in real time, open a second terminal and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; server.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Background on services.
&lt;/h2&gt;

&lt;p&gt;Services in the Pionia framework are the heart, probably the only part you will spend most of your time while developing your APIs. All normal services in Pionia extend &lt;code&gt;Pionia\Request\BaseRestService&lt;/code&gt;. A normal service in Pionia may look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;application\services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Request\BaseRestService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Response\BaseResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Porm\Porm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseRestService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// password and username are required, without them we won't proceed even&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;$password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;password_hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="no"&gt;PASSWORD_DEFAULT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'user'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'username'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="c1"&gt;//You can do more here, maybe generate a JWT token or add more checks&lt;/span&gt;
        &lt;span class="c1"&gt;// for example if the user is an active or not&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Login successful"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"User with the given username and password not found"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After building your service, you need to register it in the switch that shall be handling it from now on. If you are not aware of switches in Pionia, you can &lt;a href="https://pionia.netlify.app/documentation/pionia-services/#service-registration" rel="noopener noreferrer"&gt;read about them here in the docs&lt;/a&gt;. So, head over to our &lt;code&gt;switches&lt;/code&gt; folder, probably in the &lt;code&gt;MainAppSwitch.php&lt;/code&gt; if you have not yet created another one, and register the above service as below in the &lt;code&gt;registerServices&lt;/code&gt; method&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;     &lt;span class="cd"&gt;/**
     * Register your services here.
     *
     * @return array
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;registerServices&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'user'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="s1"&gt;'todo'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TodoService&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This is how you get your service to be auto-discovered by the kernel from now on. In typical settings, you would have added a router, and a controller to map to this service, but Pionia approaches things differently. Remember, you can have the same service registered in multiple switches. This is how we achieve the concept of API versioning since every switch is handled by its API endpoint. By default, &lt;code&gt;MainAppSwitch&lt;/code&gt; can be accessed on &lt;code&gt;/api/v1/&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In your requests, you can point to this service by sending the following.&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;http://localhost:&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;&lt;span class="err"&gt;/api/v&lt;/span&gt;&lt;span class="mi"&gt;1&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;span class="nl"&gt;"SERVICE"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ACTION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"login"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pionia"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pionia1234"&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;If you notice, &lt;code&gt;ACTION&lt;/code&gt; is the name on the &lt;code&gt;action&lt;/code&gt;/&lt;code&gt;method&lt;/code&gt; we created in our &lt;code&gt;SERVICE&lt;/code&gt;/&lt;code&gt;service&lt;/code&gt;/&lt;code&gt;class&lt;/code&gt; which we baptised the name &lt;code&gt;user&lt;/code&gt; upon registration.&lt;/p&gt;

&lt;p&gt;This is how normal services work in Pionia. &lt;/p&gt;

&lt;p&gt;Below is a complete service that performs CRUD in Piona. It is based on the following simple table called todos in a MySQL database called &lt;code&gt;todo_db&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;todo_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;todos&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;          &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="n"&gt;auto_increment&lt;/span&gt; &lt;span class="k"&gt;primary&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;       &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                        &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;                                &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;created_at&lt;/span&gt;  &lt;span class="nb"&gt;timestamp&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;CURRENT_TIMESTAMP&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;engine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;InnoDB&lt;/span&gt;&lt;span class="p"&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 php"&gt;&lt;code&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Request\BaseRestService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Request\PaginationCore&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Response\BaseResponse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Porm\exceptions\BaseDatabaseException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Porm\Porm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;BaseRestService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Returns all todos
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'db'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'created_at'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Returns a single todo
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;using&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'db'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'created_at'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Creates a new todo
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="nv"&gt;$title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;$description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$description&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Todo created successfully'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Updates a todo
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="nv"&gt;$todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// similar to `get(['id' =&amp;gt; $id])`&lt;/span&gt;

        &lt;span class="c1"&gt;// if the todo is not found, we throw an exception&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BaseDatabaseException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Todo not found'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nv"&gt;$todo&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nv"&gt;$todo&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// we update in a transaction as below&lt;/span&gt;
        &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;inTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'title'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Todo &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt; updated successfully"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Deletes a todo
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requires&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="nv"&gt;$todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$todo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BaseDatabaseException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Todo not found'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$deleted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;inTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt;$deleted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nv"&gt;$deleted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$deleted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BaseDatabaseException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Todo not deleted'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Todo &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt; deleted successfully"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Returns a random todo object if the size is not defined or 1,
     * else returns an array of random todos
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'size'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Porm&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Returns a paginated list of todos
     * @throws Exception
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;paginatedList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;BaseResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'offset'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'limit'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nv"&gt;$paginator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PaginationCore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'todos'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'db'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$paginator&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;paginate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;BaseResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And since our &lt;code&gt;TodoService&lt;/code&gt; is already registered, that's all we need to do, no adding extra routes, no adding controllers, just start hitting the &lt;code&gt;actions&lt;/code&gt; in your requests and you should get uniform responses from all the above actions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;However much this is not alot to do, and the only thing to do in Pionia(building services), all the above actions in our &lt;code&gt;TodoService&lt;/code&gt; can be omitted and we still get the same functionality, This is where our &lt;code&gt;Generic Services&lt;/code&gt; come in!&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Todo Service, The Generic Way.
&lt;/h2&gt;

&lt;p&gt;If your logic is not more than &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;delete&lt;/code&gt;, &lt;code&gt;paginate&lt;/code&gt;, &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;, &lt;code&gt;delete&lt;/code&gt;, or &lt;code&gt;retrieve&lt;/code&gt; then Generic Services might be all you need. &lt;/p&gt;

&lt;p&gt;Pionia provides both generic services and mixins to use. Mixins can be put together to put up your entire new Generic Service. &lt;/p&gt;

&lt;p&gt;Provided mixins include &lt;code&gt;ListMixin&lt;/code&gt;, &lt;code&gt;CreateMixin&lt;/code&gt;, &lt;code&gt;DeleteMixin&lt;/code&gt;, &lt;code&gt;UpdateMixin&lt;/code&gt;, &lt;code&gt;RandomMixin&lt;/code&gt; and &lt;code&gt;RetrieveMixin&lt;/code&gt;. Under the hood, even Generic services are just combining these Mixins while extending &lt;code&gt;GenericService&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Provided Generic Services include &lt;code&gt;RetrieveCreateUpdateService&lt;/code&gt;, &lt;code&gt;RetrieveListCreateService&lt;/code&gt;, &lt;code&gt;RetrieveListCreateUpdateDeleteService&lt;/code&gt;, &lt;code&gt;RetrieveListDeleteService&lt;/code&gt;, &lt;code&gt;RetrieveListRandomService&lt;/code&gt;, &lt;code&gt;RetrieveListUpdateDeleteService&lt;/code&gt;, &lt;code&gt;RetrieveListUpdateService&lt;/code&gt; and &lt;code&gt;UniversalGenericService&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the above Generics don't combine the mixins in the way you want, you can extend &lt;code&gt;GenericService&lt;/code&gt; and call all the mixins you want to use thus creating your custom generic service. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Remember, to use mixins, you must be extending &lt;code&gt;Pionia\Generics\Base\GenericService&lt;/code&gt; not the normal &lt;code&gt;BaseRestService&lt;/code&gt; we extended before. Also, remember that mixins are just PHP traits and should be used that way.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To refactor our &lt;code&gt;TodoService&lt;/code&gt;, we shall need the last mentioned generic service, &lt;code&gt;UniversalGenericService&lt;/code&gt; as it uses all the defined mixins.&lt;/p&gt;

&lt;p&gt;Let's start by changing the class we extend. Refactor this as below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Generics\UniversalGenericService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ... rest of the imports&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;UniversalGenericService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;// ... rest of your actions&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we do anything, let's first define the table we want to target in the database. We use the $table property for this. This is a compulsory feature and must be defined for all generic views.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Generics\UniversalGenericService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ... rest of the imports&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;UniversalGenericService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ... rest of your actions&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Secondly, from our &lt;code&gt;list&lt;/code&gt; action, we are defining columns we want to return, however, we are defining all. If you want to return a certain range of columns only, we define the &lt;code&gt;$listColumns&lt;/code&gt;(&lt;em&gt;which defaults to all&lt;/em&gt;) and pass the columns we want to return. Let's just still pass all though it is the default behavior of the service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Generics\UniversalGenericService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ... rest of the imports&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;UniversalGenericService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$listColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'created_at'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// ... rest of your actions&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, we can delete the &lt;code&gt;list&lt;/code&gt; action from our service. That's complete!&lt;/p&gt;

&lt;p&gt;Our second target action is now &lt;code&gt;details&lt;/code&gt;. This one can be replaced by defining the &lt;code&gt;$pk_field&lt;/code&gt; which defaults to &lt;code&gt;id&lt;/code&gt;. Since our primary key field for our &lt;code&gt;todo&lt;/code&gt; table is also &lt;code&gt;id&lt;/code&gt;, we don't need to define it, we just need to delete it too! Remember, this one also uses the defined &lt;code&gt;$listColumns&lt;/code&gt; for columns to return from the DB.&lt;br&gt;
The &lt;code&gt;RetrieveMixin&lt;/code&gt; also defines another sister action to this called &lt;code&gt;retrieve&lt;/code&gt;, so in your request, you can use &lt;code&gt;ACTION&lt;/code&gt; as &lt;code&gt;details&lt;/code&gt; or &lt;code&gt;retrieve&lt;/code&gt;, the two will perform the same thing.&lt;br&gt;
Since we already have all we need, we can drop the &lt;code&gt;details&lt;/code&gt; action too!&lt;/p&gt;

&lt;p&gt;Our third action is &lt;code&gt;create&lt;/code&gt;. For this, we &lt;strong&gt;must&lt;/strong&gt; define the &lt;code&gt;$createColumns&lt;/code&gt; to define those columns we shall be looking for from the request(required) to create a record. Let's add the property now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Generics\UniversalGenericService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ... rest of the imports&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;UniversalGenericService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$listColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'created_at'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$createColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// ... rest of your actions&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After adding, go ahead and delete it too!&lt;/p&gt;

&lt;p&gt;Our fourth action is &lt;code&gt;update&lt;/code&gt;. For this, we require the &lt;code&gt;$pk_field&lt;/code&gt; and can also &lt;strong&gt;optionally&lt;/strong&gt; define the &lt;code&gt;$updateColumns&lt;/code&gt;. If undefined, the responsible mixin checks if any of the properties were defined in the request, and will update only those.&lt;br&gt;
Let's add the &lt;code&gt;$updateColumns&lt;/code&gt; and give it the only properties we intend to update.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Generics\UniversalGenericService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// ... rest of the imports&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;UniversalGenericService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$listColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'created_at'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$createColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$updateColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// ... rest of your actions&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now drop the &lt;code&gt;update&lt;/code&gt; action too!&lt;/p&gt;

&lt;p&gt;For our fifth action, &lt;code&gt;delete&lt;/code&gt;, we only need the &lt;code&gt;$pk_field&lt;/code&gt; which is by default &lt;code&gt;id&lt;/code&gt;, so we shall be checking if &lt;code&gt;id&lt;/code&gt; was passed in the request, and then we delete the associated record. So, just delete it, we already have all we need!&lt;/p&gt;

&lt;p&gt;Now to our sixth action, &lt;code&gt;random&lt;/code&gt;, this also uses the &lt;code&gt;$listColumns&lt;/code&gt; to determine the columns to fetch from the DB per record. We already have out property defined, so, just drop it too!&lt;/p&gt;

&lt;p&gt;For our seventh action, &lt;code&gt;paginatedList&lt;/code&gt;, we can drop it, and in any request, we target our &lt;code&gt;list&lt;/code&gt; action, but we define any of the following pairs of keys in our request. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;limit&lt;/code&gt; and &lt;code&gt;offset&lt;/code&gt; on the request object level.
&lt;/li&gt;
&lt;/ol&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="nl"&gt;"SERVICE"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"ACTION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"offset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&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;ol&gt;
&lt;li&gt;
&lt;code&gt;PAGINATION&lt;/code&gt; or &lt;code&gt;pagination&lt;/code&gt; object on the request with &lt;code&gt;limit&lt;/code&gt; and &lt;code&gt;offset&lt;/code&gt; keys.
&lt;/li&gt;
&lt;/ol&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="nl"&gt;"SERVICE"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"ACTION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"PAGINATION"&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;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"offset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&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="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;SEARCH&lt;/code&gt; or &lt;code&gt;search&lt;/code&gt; object on the request object with &lt;code&gt;limit&lt;/code&gt; and &lt;code&gt;offset&lt;/code&gt; keys.
&lt;/li&gt;
&lt;/ol&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="nl"&gt;"SERVICE"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"ACTION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"SEARCH"&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;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"offset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: Both the &lt;code&gt;limit&lt;/code&gt; and &lt;code&gt;offset&lt;/code&gt; keys must be defined for pagination to kick in.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And just like that, our service now has been reduced to the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Generics\UniversalGenericService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;UniversalGenericService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$listColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'created_at'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$createColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$updateColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's do a little more cleanup. As we had mentioned earlier, if we are listing all columns from our table, then we don't need to define the &lt;code&gt;$listColumns&lt;/code&gt; property, let's remove that too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Generics\UniversalGenericService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;UniversalGenericService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$createColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$updateColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, since our &lt;code&gt;update&lt;/code&gt; can also discover the columns to update from the request data, let's remove the &lt;code&gt;$updateColumns&lt;/code&gt; too!&lt;/p&gt;

&lt;p&gt;And we are left with the following as our new &lt;code&gt;TodoService&lt;/code&gt; but still exposing the actions of &lt;code&gt;list&lt;/code&gt;(all and paginated), &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;, &lt;code&gt;delete&lt;/code&gt;, &lt;code&gt;retrieve&lt;/code&gt; or &lt;code&gt;details&lt;/code&gt; and &lt;code&gt;random&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Pionia\Generics\UniversalGenericService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TodoService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;UniversalGenericService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"todo"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;?array&lt;/span&gt; &lt;span class="nv"&gt;$createColumns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also override how we get a single record and multiple records. You might not need it, but sometimes you may need to add &lt;code&gt;where&lt;/code&gt; clauses and other conditions as you see fit. For that, you can &lt;a href="https://pionia.netlify.app/documentation/generic-services/#overriding-getters" rel="noopener noreferrer"&gt;read about it in this section in the docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Also, you may want to add your other actions in the same generic service, this is fully supported and will work as if you're in normal services, however, make sure none of those actions share the names with the provided mixin actions or otherwise you stand a chance of overriding the provided actions.&lt;/p&gt;

&lt;p&gt;This also drives to the last point, what if you intend to override the default action? that's also okay! You can also look into it under &lt;a href="https://pionia.netlify.app/documentation/generic-services/#overriding-actions" rel="noopener noreferrer"&gt;this section of the docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Welcome to Pionia Framework, where we believe in both developer and program performance, writing precise and maintainable codebase with simplicity both at the front end and the back end!&lt;/p&gt;

&lt;p&gt;Let me hear what you say about the Pionia Framework specifically about generic services. Happy coding!&lt;/p&gt;

</description>
      <category>pionia</category>
      <category>php</category>
      <category>webdev</category>
      <category>api</category>
    </item>
    <item>
      <title>Moonlight Architecture - The Old-New</title>
      <dc:creator>Tumusiime Ezra Jnr</dc:creator>
      <pubDate>Sun, 30 Jun 2024 13:54:52 +0000</pubDate>
      <link>https://dev.to/jet_ezra/moonlight-architecture-the-old-new-4ph5</link>
      <guid>https://dev.to/jet_ezra/moonlight-architecture-the-old-new-4ph5</guid>
      <description>&lt;p&gt;&lt;a href="https://pionia.netlify.app/moonlight/moonlight-architecture/" rel="noopener noreferrer"&gt;Moonlight Architecture&lt;/a&gt; is an architecture that has existed for a while but remained nameless. Therefore, it is not right to say it is a new architecture yet most developers and companies have been using it. It borrows its features from commonly used architectures of MVC, gRPC, Graphql and Micro Services. Most of the features may highly sound, look more like MVC combined with Graphql.&lt;/p&gt;

&lt;h2&gt;
  
  
  Features of Moonlight.
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;REST only. Moonlight is meant for only REST applications. It does not support any form of templating. This is a design philosophy, whereby, it lets frontend frameworks handle frontend work while serving them APIs in the most elegant manner.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also Moonlight architecture is framework and language agnostic, implying that you can use it with your favourite framework in your favourite language. If you're coming from a PHP background, a framework - &lt;a href="https://pionia.netlify.app" rel="noopener noreferrer"&gt;Pionia&lt;/a&gt;, has already been put up to get you started, however, you can configure your favourite frameworks to work with this architecture. This has already been done with frameworks such as Spring Boot in Java(an excellent and pioneer framework for the architecture), Django Rest Framework in Python(worked excellently too) and Laravel in PHP(though some few features were not pulled off right).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Moonlight encourages a single API endpoint for your entire API version, which means, all version APIs can be served at /api/v1/, then version two on /api/v2/. This is the only route you should have for your entire API. No query parameters, no relative paths but only one endpoint.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Moonlight, encourages(enforces) all requests to the backend to be performed over POST. This has security benefits since the body of POST requests is usually logged while encrypted on a web server, thus keeping your requests secure to your application server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Single request format. The architecture encourages using either JSON or FormData if supported in your language or framework. Each request must define &lt;code&gt;SERVICE&lt;/code&gt; and &lt;code&gt;ACTION&lt;/code&gt; targeted. And the rest of the data as key-value pairs.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// POST https://exampleapi.com/api/v1/&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;SERVICE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;ACTION&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1234567&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;moonlight&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Single Response Format. The response must define the return code, return message, return data, and any extra data the server wants to communicate to the front end. In this case, the return code must be defined and by conventional, &lt;code&gt;0&lt;/code&gt; is reserved for success, any other codes indicate failure but this can be customised to your business needs.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// POST https://exampleapi.com/api/v1/&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;returnCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 0 for success, any other for error or warning&lt;/span&gt;
  &lt;span class="nx"&gt;returnObject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;token_here&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="c1"&gt;// response data fro the server, can take any type according to the request&lt;/span&gt;
  &lt;span class="nx"&gt;returnMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Welcome back John Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// message you want the frontend to show&lt;/span&gt;
  &lt;span class="nx"&gt;extraData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="c1"&gt;// any other data you want to pass.&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;All requests that reach your application server must return a 200 OK status code whether they are resolved with an error or not. In cases of errors, a return code that is not &lt;code&gt;0&lt;/code&gt; can be returned, with a clean, descriptive error message as the return message.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Moonlight introduces the concept of switches, these represent a certain version of your API and register all services that are available in that version. Their main job is to read the incoming request, determine which service was defined and call it passing their entire request data. The switch also catches all uncaught exceptions in the request and returns a cleaner response similar to what we determined above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Services in Moonlight are central holders of your business logic, this is where you write all your actions specific to that service. An example of a service(class) can be &lt;code&gt;AuthService&lt;/code&gt; that defines actions(methods) such as &lt;code&gt;login&lt;/code&gt;, &lt;code&gt;resetPassword&lt;/code&gt;, and &lt;code&gt;register&lt;/code&gt;. All these must return the same response format. Actions are responsible for querying the database, validating the requested data and requesting any external third party that you might be integrating with.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Known Issues With Architecture.
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Strict(typed) languages such as Java, C# and Golang, may dictate you to stick to only JSON data. However, in non-strict languages like JS, Python, and PHP(which are commonly used for the web), you can mix both form data and JSON. This only affects uploading multipart files.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is currently the only known issue so far affecting the architecture.&lt;/p&gt;

&lt;p&gt;If you are interested in this architecture, you can &lt;a href="https://pionia.netlify.app/moonlight/moonlight-architecture/" rel="noopener noreferrer"&gt;read more about it here&lt;/a&gt;. Also, you can &lt;a href="https://pionia.netlify.app/documentation/introduction/#installation" rel="noopener noreferrer"&gt;try out Pionia for your next API application&lt;/a&gt;. Pionia provides full implementation of the architecture. You will be surprised how much you need to pull off an API!&lt;/p&gt;

&lt;p&gt;Goodluck and happy coding!&lt;/p&gt;

</description>
      <category>php</category>
      <category>pionia</category>
      <category>webdev</category>
      <category>restapi</category>
    </item>
    <item>
      <title>Yii2, PHP the easy way</title>
      <dc:creator>Tumusiime Ezra Jnr</dc:creator>
      <pubDate>Wed, 23 Mar 2022 13:39:26 +0000</pubDate>
      <link>https://dev.to/jet_ezra/yii2-php-the-easy-way-429j</link>
      <guid>https://dev.to/jet_ezra/yii2-php-the-easy-way-429j</guid>
      <description>&lt;p&gt;Welcome back to my other writing about tech, today we discuss about Yii2, yes, Yii2 also known as Yes it is, for security, fast and effecient. &lt;/p&gt;

&lt;p&gt;Whereas most of us confuse the two, but Yii2 is not an extension of yii1, it is a complete re-write of first version which implies yii2 was a complete re-write ground-up, not extension of yii1. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Background&lt;/strong&gt;&lt;br&gt;
Compared to the most of the powerful frameworks, yii is slightly younger, that is, it first got its official release in December 3rd, 2008 but this was version 1 and it was not super-production-ready and battle-tested to start the competition with the then existing Django, Spring etc. Therefore a new, Version 1.1.2, which was more battle-tested had to be released and that was on March 14th, 2010. And that's how we see the coming up of yii1. But the journey did not stop, this version still had some loops here and there and the developers felt there was more need for further improvement however, they could not tamper with the already existing mature-seeming version 1.1.2, and there was also a tremendous job that was taking place to PHP itself which made PHP run faster and better. Therefore in 2013, May, the first unstable version of yii2 was released which was later followed by the release of the stable version in 2018 October that supported new versions of PHP. Yii2 currently fully supports PHP 8+.&lt;br&gt;
Version 3 of the framework is in progress and can be found &lt;a href="https://www.yiiframework.com/yii3-progress" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting started with Yii2.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yii2 gives you two templates of projects you can start from and these are as follows.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The basic template (which is most likely what you want)&lt;/li&gt;
&lt;li&gt;The advanced template.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Requirements&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;PHP installed and running. especially PHP7.2+&lt;/li&gt;
&lt;li&gt;You will need composer installed. You can quickly install composer from &lt;a href="https://getcomposer.org/download/" rel="noopener noreferrer"&gt;composer official download page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Apache2 or nginx installed and running.&lt;/li&gt;
&lt;li&gt;Database of your choice running e.g. PostgreSQL or MySQL. You can find the list of all &lt;a href="https://www.yiiframework.com/doc/guide/2.0/en/db-dao" rel="noopener noreferrer"&gt;databases supported by Yii here&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This short tutorial will illustrate the setup of yii2 basic project, you may find the &lt;a href="https://github.com/yiisoft/yii2-app-advanced/blob/master/docs/guide/README.md" rel="noopener noreferrer"&gt;setup of the advanced project here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installation.&lt;/strong&gt;&lt;br&gt;
You can quickly set up a yii2 basic project by running the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer create-project --prefer-dist yiisoft/yii2-app-basic basic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;composer&lt;/code&gt; is the package manager for PHP applications and can be used to perform various action as seen by running &lt;code&gt;composer&lt;/code&gt; in your terminal.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;create-project&lt;/code&gt; is the yii2 command that tells yii that you are actually creating a new application.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--prefer-dist yiisoft/yii2-app-basic&lt;/code&gt; this tells yii2 the template type you would like to start with. In our case we chose the basic template.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;basic&lt;/code&gt; is the application name, this can be any name, like polls, facebook, blog.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now since you have application, let's navigate to it using and open it with vs code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd appname &amp;amp;&amp;amp; code .  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;appname&lt;/code&gt; with your application name you just created. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Project structure&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fae8kc3xbvywl2hzmnw3m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fae8kc3xbvywl2hzmnw3m.png" alt="Image description" width="269" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The boilerplate seems alot but let's break it down in a minute.&lt;/p&gt;

&lt;p&gt;Yii2 is in the nature of MVC that is Model View Controller and here, they do exactly how they sound. That is, models are placed in models, Views that is where you place what users see and finally controllers carry the mapping and logic of your entire application.&lt;/p&gt;

&lt;p&gt;And we have completed the whole boilerplate! WAIT, HAVE WE?&lt;/p&gt;

&lt;p&gt;So what are the rest?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;assets&lt;/code&gt; help you to configure your JS, CSS and other dependencies of your entire application also known as &lt;code&gt;Application Assets&lt;/code&gt; and these are done in &lt;code&gt;AppAsset.php&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;commands&lt;/code&gt; these help you to register your new commands with the application. These can later be later accessed and ran via your console.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;config&lt;/code&gt; as the name suggests, this is where the entire application configurations sit. From databases, to configuring modules and many more.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;controllers&lt;/code&gt;, as mentioned above, this is where routing and app logic resides. Logic that ranges from authentication, opening pages, redirecting and many more.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mail&lt;/code&gt;, this is functional for sending emails.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;models&lt;/code&gt;, the database tables' representation in your code. These help you to interuct with database tables as PHP classes.&lt;/li&gt;
&lt;li&gt;... More of these files you may never require them at all. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vendor&lt;/code&gt; stores your dependencies you have installed, look at this as your node_modules folder, or your virtualenv in python.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;views&lt;/code&gt; contains the pages(HTML) that users finally interuct with.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;web&lt;/code&gt; This is the entry folder. Your application will first get into this folder to access your index.php, which will redirect it accordingly thus running the entire application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To run our application just get the root directory, make sure you are on the level of &lt;code&gt;yii&lt;/code&gt; file. And run the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;php&lt;/span&gt; &lt;span class="n"&gt;yii&lt;/span&gt; &lt;span class="n"&gt;serve&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to &lt;a href="http://localhost:8080/" rel="noopener noreferrer"&gt;http://localhost:8080/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If everything was successful, you should be seeing the page below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fasm4t5bvwbfcxzy4tm5p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fasm4t5bvwbfcxzy4tm5p.png" alt="Image description" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that is it!! You have your first PHP Yii2 framework app up and running.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages of YII2&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication and authorization out of the box. This comes with pre-configured helpers and classes to handle sessions, roles and permissions and many more.&lt;/li&gt;
&lt;li&gt;Inbuilt ORM(Object Relational Mapper) that supports over 6 databases and supports working with already existing databases with ease!&lt;/li&gt;
&lt;li&gt;Code generation. In Yii2, you may find it crazy but in most cases you will will find code generation being automated by the gii module. You can find this at localhost:8080/gii. This enables generate modules, models, views, CRUD and many more.&lt;/li&gt;
&lt;li&gt;Bootstrap 4 out of the box. With Yii2 you don't need to configure bootstrap and jQuery as these two come preconfigured for you to start using without any additional work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let me hear from you about the performance of yii2 and if you are a fun too! otherwise, goodluck with your yii journey.&lt;/p&gt;

</description>
      <category>yii2</category>
      <category>php</category>
      <category>programming</category>
      <category>frameworks</category>
    </item>
    <item>
      <title>Go the way to Go</title>
      <dc:creator>Tumusiime Ezra Jnr</dc:creator>
      <pubDate>Wed, 16 Mar 2022 20:04:05 +0000</pubDate>
      <link>https://dev.to/jet_ezra/go-the-way-to-go-35e2</link>
      <guid>https://dev.to/jet_ezra/go-the-way-to-go-35e2</guid>
      <description>&lt;p&gt;Well, well well, today we need to take a small teleportation to the future of software development. But before let's first look at the background.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In 1972, a very wise guy called Dennis Ritchie develops the first version of C at Bell Labs.&lt;/li&gt;
&lt;li&gt;In 1979, another smart brain Bjarne Stroustrup enhances C to add more object oriented fetures such as classes also at Bell labs. C++ was made open for everyone to use in 1985.&lt;/li&gt;
&lt;li&gt;In 1991, we see the birth of the worlds most powerful language(as of the present), python, by Guido Van Rossum.&lt;/li&gt;
&lt;li&gt;In 1994, a language which was ignited to truck who viewed Rasmus Lerdolf's resume, called Personal Home Page(PHP), that was later released for use by others in 1995, which we may call its birth year.&lt;/li&gt;
&lt;li&gt;In the same year, 1995, we see another smart brain named James Gosling developed Java at Sun Microsystems though rumors say that it was ignited in 1991 but let the world to know about it in 1995. &lt;/li&gt;
&lt;li&gt;Also in the same year, 1995, we also see the birth of the world's second best programming language, JavaScript, developed by Brendan Eich, currently may be the most popular programming language!.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;... the list is endless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But here is the catch&lt;/strong&gt;&lt;br&gt;
The first multi-core processor was developed by IBM, in 2001, &lt;a href="https://www.ibm.com/ibm/history/ibm100/us/en/icons/power4/" rel="noopener noreferrer"&gt;more details can be read here&lt;/a&gt;  and at this time the only latest programming language was C# which was created in 2000, one year before the birth of multi-core processor architecture.&lt;/p&gt;

&lt;p&gt;Therefore, with the new architecture in place, languages started putting measures to use this great feature, but that was not their nature. We see JavaScript introducing promises for asynchronous performance, python, C, Java, C++, C# do the same so as to support the multiple events since the number of threads to work on tasks were increasing. But these were all added features and of these programming languages had this by default. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To our rescue!&lt;/strong&gt;&lt;br&gt;
Robert Griesemer, Rob Pike, and Ken Thompson in 2012(when it was made public), 10 years back from the time of writing this article, (but developed in 2007), developed a language that combines all the good parts of the dear oldies, Java, Python, JS, C++, C#, C and ignores the worst parts they have, at Google. The language gets its name from (you guessed it right), Google as that's where it was developed from. Various features that you need to install as libraries, packages ..., will be implemented by default in Go. &lt;/p&gt;

&lt;p&gt;Well, right now, the transition is not instant, but the future will dictate us to fully move to Go as most of the biggest companies have already changed their performance sensitive programs to Go. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Go?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go is popular for cloud-based or server-side applications. &lt;/li&gt;
&lt;li&gt;DevOps and site reliability automation are also popular ways to use Go. &lt;/li&gt;
&lt;li&gt;Many command-line tools are written in Go.&lt;/li&gt;
&lt;li&gt;Go is used in the world of artificial intelligence and data science.&lt;/li&gt;
&lt;li&gt;Some use Go from micro-controller programming, robotics, and games.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, Go really shines the most when it comes to infrastructure. Some of the most popular infrastructure tools today are written in Go — such as Kubernetes, Docker, and Prometheus.&lt;br&gt;
Generally, wherever you need a lot of performance and concurrency, Go has got you covered. &lt;/p&gt;

&lt;p&gt;Speed comparison between Go and Java.&lt;/p&gt;

&lt;p&gt;Go results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Factorial   Time To calculate factorial
10000       0.03 seconds
50000       0.41 seconds
100000      2.252 seconds
500000      68.961 seconds
1000000     224.135 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Java results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Factorial   Time To calculate factorial
10000       0.112 seconds
50000       1.185 seconds
100000      2.252 seconds
500000      89.500 seconds
1000000     385.868 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a small sample test, but you can explore more with other languages and see how Golang beats the rest in performance.&lt;/p&gt;

&lt;p&gt;Note: It is only in Golang where you do not even think about async and sync as Go by default is the only asynchronous programming language ever made.&lt;/p&gt;

&lt;p&gt;Whereas python, C#, Java, C ..., are still proving to be our present, after teleporting to the future, I found Go being widely used more than anything else!! So start learning it today from &lt;a href="https://go.dev/doc/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>functional</category>
      <category>productivity</category>
      <category>performance</category>
    </item>
    <item>
      <title>Django vs Flask, what to choose!</title>
      <dc:creator>Tumusiime Ezra Jnr</dc:creator>
      <pubDate>Tue, 08 Feb 2022 09:12:13 +0000</pubDate>
      <link>https://dev.to/jet_ezra/django-vs-flask-what-to-choose-5ceo</link>
      <guid>https://dev.to/jet_ezra/django-vs-flask-what-to-choose-5ceo</guid>
      <description>&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
Introduction

&lt;ul&gt;
&lt;li&gt;
Flask

&lt;ul&gt;
&lt;li&gt;Background&lt;/li&gt;
&lt;li&gt;Who uses flask&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Django

&lt;ul&gt;
&lt;li&gt;Background&lt;/li&gt;
&lt;li&gt;Who uses Django&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Similarities&lt;/li&gt;

&lt;li&gt;Differences&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Hello, hope you are doing well, well, this is 2022 knocking at the door and we need to start doing things its new way it is coming along with.&lt;br&gt;
Whereas there are more than 50 frameworks of Python, there are only two of these that have continuously become the kings of the web, flask and Django at least as far as 2021.&lt;br&gt;
These two frameworks seem to be the most mature and most loved on the web by many beginners, advanced developers and companies. They give us a chance to use the world's best language for full stack development. Let's break them and we get to know which to learn and use when! Can we roll!!&lt;/p&gt;
&lt;h3&gt;
  
  
  Flask &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Background &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Flask was created by Armin Ronacher of Pocoo, an international group of Python enthusiasts formed in 2004. According to Ronacher, the idea was originally an April Fool's joke that was popular enough to make into a serious application. The name is a play on the earlier Bottle framework.&lt;br&gt;
When Ronacher and Georg Brandl created a bulletin board system written in Python, the Pocoo projects Werkzeug and Jinja were developed.&lt;/p&gt;

&lt;p&gt;Flask's philosophy according to this article is to let the developer take on the driver's seat and have total/full control over the application they are developing.&lt;br&gt;
This has made the framework become the no.1 choice to most of the developers that love doing things their own way.&lt;/p&gt;

&lt;p&gt;Flask code sample:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello, World!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above code, you have a full application that outputs &lt;code&gt;Hello, World&lt;/code&gt; in the browser running on &lt;code&gt;http://localhost:5000&lt;/code&gt;, amazing, right!&lt;/p&gt;

&lt;h4&gt;
  
  
  Who uses flask &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Well, flask being a python light weight framework, most of the companies have picked it to play a big role in building micro-services. As we have seen in the above code snippet, with just one file, you have a fully working app. Therefore, over 900 companies may not entirely be depending on flask as the primary backend framework but include it in their stack.&lt;br&gt;
This list only shows the top 10.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Netflix&lt;/li&gt;
&lt;li&gt;Reddit&lt;/li&gt;
&lt;li&gt;Lyft&lt;/li&gt;
&lt;li&gt;CRED&lt;/li&gt;
&lt;li&gt;Trivago&lt;/li&gt;
&lt;li&gt;Zalando&lt;/li&gt;
&lt;li&gt;MIT&lt;/li&gt;
&lt;li&gt;Patreon&lt;/li&gt;
&lt;li&gt;ML&lt;/li&gt;
&lt;li&gt;Sendcloud&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As per this writing, Flask had 2.2k watches, 57.1k stars and 14.7k  forks on github, these may have changed by the time you are reading this but you can &lt;a href="https://github.com/pallets/flask" rel="noopener noreferrer"&gt;click here for the current standings&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Django &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Django (/ˈdʒæŋɡoʊ/ JANG-goh; sometimes stylized as django) is a Python-based free and open-source web framework that follows the model–template–views (MTV) architectural pattern. It is maintained by the Django Software Foundation (DSF), an independent organization established in the US as a 501(c)(3) non-profit. &lt;/p&gt;

&lt;h4&gt;
  
  
  Background &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Django was created in the fall of 2003, when the web programmers at the Lawrence Journal-World newspaper, Adrian Holovaty and Simon Willison, began using Python to build applications. Jacob Kaplan-Moss was hired early in Django's development shortly before Simon Willison's internship ended. It was released publicly under a BSD license in July 2005. This framework has been around for over 16 years atleast as per this writing! The framework was named after guitarist Django Reinhardt.&lt;/p&gt;

&lt;h4&gt;
  
  
  Who uses django &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Well various applications/companies or even tools may not be using Django as the framework but it's counterpart framework Django Rest framework which is a derivative of the same.&lt;/p&gt;

&lt;p&gt;The list shows the companies currently using Django in their progressive work. The list only shows the top 10 but there are more.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Disqus&lt;/li&gt;
&lt;li&gt;Instagram&lt;/li&gt;
&lt;li&gt;Bitbucket&lt;/li&gt;
&lt;li&gt;MacArthur Foundation&lt;/li&gt;
&lt;li&gt;Mozilla&lt;/li&gt;
&lt;li&gt;National Geographic&lt;/li&gt;
&lt;li&gt;Open Knowledge Foundation&lt;/li&gt;
&lt;li&gt;Pinterest&lt;/li&gt;
&lt;li&gt;Open Stack
&lt;/li&gt;
&lt;li&gt;Spotify&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F763yvx8wq6pefmzx6rnk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F763yvx8wq6pefmzx6rnk.jpg" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As per this writing, Django had 2.3k watches, 62.1k stars and 26.5k  forks on github, these may have changed by the time you are reading this but you can check the  &lt;a href="https://github.com/django/django" rel="noopener noreferrer"&gt;Django repo for the current stand&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Similiraties &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Well, no matter how they seem to be, the two frameworks share somethings in common which you can not under look. And the matter of the fact, if you are ready comfortable with one, you will find it extremely easy to move one to the next. Like the process is seamless.&lt;/p&gt;

&lt;p&gt;Here are the similarities you will find in both.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Python frameworks&lt;/strong&gt;. Well, without knowledge of python, then you won't be able to write the two frameworks. The are highly Object oriented, and therefore all functions, classes and data structures from python itself, can be used in both.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fullstack frameworks&lt;/strong&gt;. Both are independent fullstack frameworks, that is, you will not need any other framework alongside them to develop the backend, frontend etc. They come with inbuilt template engines to handle the front-end and use python to handle the backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ORM for models&lt;/strong&gt;. The frameworks use Object Relational Mappers to provide quick interactions with the database. Whereas Flask does not ship in with this functionality, a special tool to achieve the same has been developed called &lt;a href=""&gt;Flask-SQLAlchamey&lt;/a&gt; .On the other hand, the ORM functionality is in-built with django and it's one of those features Django beats most of the other frameworks on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request-Response behaviour&lt;/strong&gt;. With both frameworks you will not miss finding features such as views which will receive requests, perform some logic and map them to the right response. This response maybe returning a new page, some json, or file. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Routes/urls&lt;/strong&gt;. Whereas the design differs, the functionality does not. These are mappers, which tell the frameworks which view to return on which request.
6.** Sessions and authentication**. Whereas, you may not start the sessions automatically with flask, helper functions for starting, updating, deleting sessions, and performing authentication are provided for by the frameworks. Some of these features can be achieved with some extra libraries in flask, but relying on external libraries in django is upon you. Whichever choice you opt for, you will find it easy in both to handle the functionalities. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In-built template engines&lt;/strong&gt;. Whereas they may not entirely be the same, the frameworks come with the inbuilt way of building templates(what users see). With these, python functionalities such loops, conditionals, string laterals and many more are presented. Flask uses Jinja2, but with django, you can choose to use Jinja2 but this is not their default. Django has defined its own template engine called django templates, which works closely similar to Jinja2 with little upgrades. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These are not the only similarities, the endless will surely be bigger, but you scan from the above for more...&lt;br&gt;
Next, let's move on how the two differ.&lt;/p&gt;

&lt;h2&gt;
  
  
  Differences &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;There will be a few distinctions between the two frameworks, and that's the reason why I had put it that switching from one to another shall really be seamless. Let's see how they differ.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Architecture&lt;/strong&gt;. Django is MVT(That is, Model-View-Template). Now do not take "View" for how other frameworks of MVC(Model-View-Controller) take it, Model-will still be Model, View will be equivalent to Controller and  Template will equivalent to View in MVC. Somehow confusing right!, please read the docs to understand how django handles this feature. Django stores and names these files accordingly and most of them are provided by default.
On the other hand, Flask is a modular framework, which means, one file can even contain the whole app. Whereas, the architecture is internally maintained as for django, the structure is entirely upon you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt;. Django is meant for developers who want to get tasks complete in time. That's why you will find most of the features provided for by default. This may look a good thing and will actually do the right work for you, but this means you will have less freedom of updating the defaults which will require extra knowledge of the framework to update these features. On the other hand, Flask is entirely flexible, ground up. In brief, there is no convention of designing a Flask application. This also looks good for the start, but when the project starts getting complex, new members, and/or even old team may find it hard to update the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;. Flask is highly meant to develop modular applications also known as micro services in the same project. This implies that different developers can work on different small modules independent of each other but communicating together. However, django is somehow different. Django itself is considered a project, and then inside it, you set up as many applications as you feel like. This let's django handle even the most complex project with ease. Also the development convention of django while creating these apps makes it very simple for one to divide out members to work on different modules within the same project without necessarily handling them in a distributed format. Also, plugging in a new app is very seamless also and does not affect the other applications ran in the same project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;. Whereas in django, starting from the user, and all the forms of authentications such as creating accounts, logging in, resetting and changing passwords, confirming passwords and many more are inbuilt, flask loses out on some of these features and you will end up building them from scratch or depending on third-party libraries. Features like cryptography, click-jacking, CSRF and worked upon by django by default. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning curve&lt;/strong&gt;. If you already know python, Flask should take at most a week to write your first application. This differs with django, most developers have confessed that understanding the file structure of the framework has become an issue, however, understanding this flow will make django equally easier. Therefore, django will require you to at least two weeks to feel comfortable working on a good project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ORM&lt;/strong&gt;. Whereas flask depends and works well with Flask-SQLAlchamy, Django's ORM is a killer. From the process of creating models, tracking and squashing, working with more than one database, and changing from one database to the other. All these make Django ORM a killer feature especially when it comes to handling complex databases with very many tables.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;With that said and more as you will read from other developers, the question still stands, &lt;strong&gt;what do you choose?&lt;/strong&gt; &lt;br&gt;
Well, I am someone who writes both frameworks and my conclusion is thought about.&lt;/p&gt;

&lt;p&gt;When you are handling something that is not complex at all, please choose Flask. &lt;/p&gt;

&lt;p&gt;If you are working on a project with some other framework such as Express or Laravel, but wanted some independent feature to be done with python, please choose flask. &lt;/p&gt;

&lt;p&gt;Otherwise, choose django.&lt;/p&gt;

</description>
      <category>django</category>
      <category>flask</category>
      <category>python</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
