<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Code Axion The Security Breach on Medium]]></title>
        <description><![CDATA[Stories by Code Axion The Security Breach on Medium]]></description>
        <link>https://medium.com/@codeaxion77?source=rss-c43ba02a17a3------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*adSkKftYMkLAvw_8RCrzcQ.png</url>
            <title>Stories by Code Axion The Security Breach on Medium</title>
            <link>https://medium.com/@codeaxion77?source=rss-c43ba02a17a3------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Tue, 02 Jun 2026 05:06:53 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@codeaxion77/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[New Laravel + Nextjs (SSR) Starter kit]]></title>
            <link>https://medium.com/@codeaxion77/new-laravel-nextjs-ssr-starter-kit-0705904f8306?source=rss-c43ba02a17a3------2</link>
            <guid isPermaLink="false">https://medium.com/p/0705904f8306</guid>
            <category><![CDATA[laravel-framework]]></category>
            <category><![CDATA[laravel]]></category>
            <category><![CDATA[nextjs]]></category>
            <category><![CDATA[laravel-development]]></category>
            <category><![CDATA[nextjs14]]></category>
            <dc:creator><![CDATA[Code Axion The Security Breach]]></dc:creator>
            <pubDate>Sat, 28 Dec 2024 14:38:02 GMT</pubDate>
            <atom:updated>2024-12-28T14:42:13.375Z</atom:updated>
            <content:encoded><![CDATA[<p>I am thrilled to announce a new Starter kit for Laravel.<br>Introducing Laravel — Next.js (SSR-Server Side Authentication) Edition ▲</p><p>I know you’re thinking we already have one. Yes, we have one, but it does not support SSR authentication. And the best part? It’s completely stateless!</p><p>Link: <a href="https://github.com/CODE-AXION/nextjs-ssr-laravel-kit/tree/main">https://github.com/CODE-AXION/nextjs-ssr-laravel-kit/tree/main</a></p><p>Things we are gonna talk about ?</p><blockquote><strong>- Key Features &amp; Security<br>- Installation<br>- Behind the Scenes and Flow<br>- Additional Information</strong></blockquote><p>To begin with, let me tell you about the main features of this starter kit .</p><p><strong>Stateless Authentication<br></strong>Fully stateless that means we are communicating with only tokens</p><p><strong>SSR Authentication<br></strong>This gives us several advantages like SSR middlewares and to display the user data quickly</p><p><strong>Middleware checks <br></strong>for protected routes, guest routes, verify email just like laravel.<br>The middlewares are easily implemented and has all the verification checks which laravel includes</p><p><strong>Signed Double Submit CSRF Protection<br></strong>As we talked earlier this starter kit is fully stateless and you can scale it easily . You might be asking why not use Laravel CSRF protection … ?</p><p><strong>Reason:</strong> i have not relied on Laravel csrf tokens is because it’s tied to server-side sessions for handling csrf tokens and we wanted this to be completely stateless so we have used <strong>signed double submit cookie protection </strong>which is stateless and secure and does not require to work with session which gives us benefits to :</p><blockquote>— Better Integration with API-First and SPA Architectures</blockquote><blockquote>— making it more scalable and easier to manage across different server instances, especially in microservices or stateless architectures</blockquote><blockquote>— No Need for Session Storage</blockquote><blockquote>— Most recommended option from OWASP itself to protect from csrf attacks (https://<a href="http://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#signed-double-submit-cookie-recommended">cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#signed-double-submit-cookie-recommended</a>)</blockquote><p><strong>HttpOnly Cookie Secure tokens<br></strong>— We are using Http Only LAX cookie so that our cookies are not being tampered .</p><p>— Security guidelines (COOKIES, CSRF) following OWASP Guidelines</p><p>— We have followed the Best practices for the cookies and CSRF from the OWASP Guidelines itself.</p><p><strong>Refresh Token for preventing token expiration</strong></p><p>— We have implemented <strong>Refresh Token Architecture</strong> so the user does not have to log in every time .</p><p><strong>Reusable authorization helpers</strong></p><p>— If you have used Spatie roles and permission package we have provided similar helpers in the starter kit .</p><h3>Installation</h3><pre>git clone https://github.com/CODE-AXION/nextjs-ssr-laravel-kit?tab=readme-ov-file</pre><blockquote>then run the following commands</blockquote><pre>composer install<br>copy the .env.example to .env<br>php artisan key:generate<br>php artisan migrate<br>php artisan db:seed to ( generate users and roles and permission )</pre><blockquote><strong>Important Note:</strong></blockquote><blockquote>Next, ensure that you have to added the <strong>Laravel API_URL </strong>and <strong>FRONTEND_URL</strong> environment variables in the laravel <strong>.env </strong>file or you might face some issues.</blockquote><pre>API_URL=http://localhost:8000/api<br>FRONTEND_URL=http://localhost:3000</pre><p>After defining the appropriate environment variables, you may serve the Laravel application using the below Artisan command:</p><pre>php artisan serve --host=localhost --port=8000</pre><blockquote>Frontend setup :</blockquote><p>Next, cd nextjs and install its dependencies with yarn install or <strong>npm install. </strong>Then, copy the <strong>.env.example</strong> file to <strong>.env.local</strong> and supply the URL of your backend api in the <strong>.env.local</strong> file :</p><pre>NEXT_BACKEND_URL=http://localhost:8000</pre><blockquote>Important Note:</blockquote><blockquote>Generate any random key for CSRF_SECRET_KEY and add that value in the <strong>.env.local file</strong>.</blockquote><blockquote>IF YOU DONT SPECIFY THIS KEY YOUR APPLICATION WILL CRASH.</blockquote><pre>https://stackoverflow.com/questions/8855687/secure-random-token-in-node-js<br>CSRF_SECRET_KEY= //random crypto token</pre><p>Run the application via <strong>npm run dev</strong>. The application will be available at <a href="http://localhost:3000:">http://localhost:3000</a></p><p>We are now done with the installation steps you can now explore the pages and all .</p><h4>Now let’s take a deep dive On How This Starter Kit Works</h4><h4>(Behind The Scenes )</h4><p><strong>Laravel side</strong>:</p><p>We are actually using the same concept as Laravel Breeze but instead of dealing with session cookie we are returning tokens .</p><p>and we store that tokens in a Http Only Secure LAX cookies in Nextjs .</p><p><strong>Nextjs SSR side:</strong></p><p>we call these Laravel Apis in the <strong>Nextjs Backend</strong> and store the tokens in the Http Only cookies .</p><p>so How the Flow looks like ?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xJmjq8yls_OqT1q5DwKyqA.png" /></figure><blockquote>Calling APIs via Backend Proxy (Nextjs Backend)</blockquote><p>We are treating Nextjs backend as a Proxy which will call our Laravel Backend Apis. kinda like BFF .</p><p>Instead of calling the API directly, our AJAX calls will go through an API Proxy — basically a thin layer in front of the actual API.</p><p>By using this method you can host your Laravel backend to any domain you want because we have Decoupled Frontend and Backend here, you just have to configure CORS thats it.</p><p>Secondly our Laravel backend Apis wont be exposed on the frontend as it hides the details of your backend servers from the client, adding a layer of security. It ensures that clients interact with the proxy, not the backend servers directly.</p><h4><strong>Technical Details (</strong>Data Fetching<strong>):</strong></h4><p>Currently we are using Axios for data fetching .<br>so if you want to call Laravel Backend Apis which requires Authentication<br>you have to call the below Axios instance :</p><pre>import { createAxiosInstance } from &quot;@/lib/axios&quot;;<br><br>// the access token will be automatically passed no need to pass it manually<br>// pages/api/invoices.js ←- Nextjs backend api<br><br>const axios = createAxiosInstance(req, res);<br>const response = await axios.get(&#39;/api/invoices&#39;); ←- laravel backend api</pre><blockquote>Behind the scenes: The <strong>createAxiosInstance</strong> will automatically pass <strong>Bearer Tokens </strong>in the Headers.</blockquote><blockquote>and if the <strong>Access Token</strong> some how Expires it will refresh it with the <strong>Refresh Token </strong>and this will happen behind the scenes with A<strong>xios Interceptors </strong>.</blockquote><blockquote>Use this instance whenever you want to call a Laravel Backend Api which requires <strong>Authentication .</strong></blockquote><p>If you want to call Laravel Backend Apis which does not require authentication you can directly call it like this with</p><pre><br>import axios from &quot;axios&quot;;<br>the normal axios instance<br>// pages/api/users.js ←- Nextjs backend api<br>const response = await axios.get(`${process.env.NEXT_BACKEND_URL}/api/products`); ←- laravel backend api</pre><p>Now this was for the Backend Apis but we also have to make sure our Apis are protected via csrf attacks so you can just simply wrap your Nextjs Api Route handlers with this wrapper to protect from csrf attacks .</p><pre>// pages/api/login.js<br><br>import { withValidation } from &quot;@/lib/withValidation&quot;;<br><br>const handler = async (req, res) =&gt; {<br>    if (req.method !== &#39;POST&#39;) {<br><br>      return res.status(405).json({ message: &#39;Method Not Allowed&#39; });<br>    }<br>    <br><br>    // your business logic here<br>}<br><br>// verifyCsrfTokenCheck: true will be used to validate the CSRF token in our nextjs backend apis.<br>export default withValidation({ verifyCsrfTokenCheck: true })(handler);</pre><h4>What about Middlewares and User contexts ?</h4><p>Laravel provides Several Middlewares like Guest , Auth, Verify email etc…</p><p>For calling GET Apis we usually use <strong><em>getServerSideProps</em></strong> of Nextjs.<br>But instead i have created a particular Get Server Side Wrapper <strong>(withAuth)</strong></p><p>Which acts as a middleware and passing user context to view</p><p>so you can basically do it like this as a second param of withAuth wrapper you will get the user context and you can pass it as a prop if you want :</p><pre>import { withAuth } from &#39;@/lib/withAuth&#39;;<br><br>export const getServerSideProps = withAuth(async (context, user) =&gt; {<br>    const { req } = context;<br><br>    // if (!hasPermission(user, &#39;create post&#39;)) {<br><br>    //     // return redirect back to 403 page<br>    //     return {<br>    //         redirect: {<br>    //             destination: &#39;/403&#39;,<br>    //             permanent: false,<br>    //         },<br>    //     };<br>    // }<br><br>    return {<br>        props: { user }, // Pass the user data to the page component<br>    };<br>});</pre><p>By using this wrapper all the middleware checks will be applied and if you want to customize it</p><p>you can do it by adding the condition below . this will run first before the get server side function is called so you can handle any logic before the request reaches to the get server side props :</p><pre>// src/lib/withAuth.js<br><br>const user = await getUserData();<br><br>const isProtectedRoute     = PROTECTED_ROUTES.includes(context.resolvedUrl);<br>const isGuestRoute         = GUEST_ROUTES.includes(context.resolvedUrl);<br>const isEmailVerifiedRoute = context.resolvedUrl.includes(VERIFY_EMAIL_ROUTE) || context.resolvedUrl.includes(EMAIL_VERIFICATION_ROUTE);<br><br>if (!user &amp;&amp; isProtectedRoute) {<br>    // User is not authenticated and trying to access a protected route<br>    return {<br>        redirect: {<br>            destination: REDIRECT_IF_NOT_AUTHENTICATED,<br>            permanent: false,<br>        },<br>    };<br>}<br><br><br>// add more middlewares checks here</pre><h4>Some Configuration Settings</h4><p>Suppose you changed the response key of your access tokens in your Laravel Login Api .</p><p>Now you also have to change it everywhere inside the Nextjs application, so to make it easier i have created a config file named <strong><em>(utils.js)</em></strong></p><p>where you can change those key settings and it will be reflected everywhere .</p><p>Then we have the Route Service Provider file</p><p>which will be used to register the Protected and Guest routes Middlewares via withAuth wrapper.</p><p>If you want to add a new route which you want it to be protected you can add it here .</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*AULtzCB-ZmRLJKhsvWABqg.png" /></figure><p>You can check more details about it here:</p><p><a href="https://github.com/CODE-AXION/nextjs-ssr-laravel-kit?tab=readme-ov-file#route-service-provider">https://github.com/CODE-AXION/nextjs-ssr-laravel-kit?tab=readme-ov-file#route-service-provider</a></p><p>Lets talk about the some Minor points from Laravel Side and some Important information !</p><h4>Important</h4><blockquote>→ If you want to customize verify email functionality you can refer to the <strong>Notifications/VerifyEmail.php</strong> file</blockquote><pre><br>Reset password url is set in the AuthServiceProvider.php file<br><br>ResetPassword::createUrlUsing(function ($user, string $token) {<br>    return config(&#39;app.frontend_url&#39;) . &#39;/reset-password/&#39; . $token . &#39;?email=&#39; . $user-&gt;email;<br>});</pre><blockquote>→ Default expiration time for tokens are set in the <strong>config/sanctum.php</strong> file</blockquote><blockquote>→ If you want you can change it <strong>(ALWAYS GIVE EXPIRATION TIME IN SECONDS or it may lead to unexpected behaviour).</strong></blockquote><blockquote>→ Default Expiration time for <strong>Access token is 1 day </strong>and for <strong>Refresh token is 7 days.</strong></blockquote><h4>Final Words</h4><p>I made this starter starter kit because i could not find proper starter kit which has SSR authentication.</p><p>Initially I tried to made this with next-auth library but I found its implementation overly complex, especially for managing refresh tokens, cookie expiration, and other configurations, So Instead I created this starter kit to keep things simple and straightforward.</p><p>And Secondly i know … i know…. <br><em>No Typescript … or App Router</em></p><p>I made this starter kit parallelly alongside with my ongoing work. and wanted the things fast and quick so i have not included typescript as it involves alot of time and work, and the reason i used pages router is because its easy to implement , a lot of applications are still using pages router . More Developers are familiar with it .</p><p>Look the thing is Pages router solves simpler problems and was developed slowly over many years. The App router is newer, was developed faster, and has to solve more complex problems. App router is a lot more impressive than pages, but like anything else, it needs time to mature. Depending on your project . Once it gets stable i will definitely switch to App Router.</p><p>If Someone is ready to contribute this project to convert it to typescript i will be more than happy . But i don’t think i will have time to convert the whole project to typescript maybe in future i guess … ?</p><p>Well Let me know your thoughts regarding this starter kit in the comments section .</p><blockquote>— — — — — — — — — — — — — — See You In 2025 — — — — — — — — — — — — — — — —</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=0705904f8306" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Create JSON Structures Right On The Sql !]]></title>
            <link>https://medium.com/@codeaxion77/create-json-structures-right-on-the-sql-63fd122cfaac?source=rss-c43ba02a17a3------2</link>
            <guid isPermaLink="false">https://medium.com/p/63fd122cfaac</guid>
            <category><![CDATA[sql]]></category>
            <category><![CDATA[php]]></category>
            <category><![CDATA[database]]></category>
            <category><![CDATA[php-developers]]></category>
            <category><![CDATA[mysql]]></category>
            <dc:creator><![CDATA[Code Axion The Security Breach]]></dc:creator>
            <pubDate>Mon, 25 Mar 2024 11:40:25 GMT</pubDate>
            <atom:updated>2024-03-25T11:40:25.674Z</atom:updated>
            <content:encoded><![CDATA[<h3>Create JSON Structures Right On The Sql !</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HSg9xEuhK-n8kppFloGPhg.png" /></figure><p>Hello !!! my fellow core php and codeigniter developers this will be a huge time saver for ya because this concept is mostly used by core php and codeigniter devs who usually write raw SQL in their projects and even if you don’t know its okay we’ve got you covered here !</p><p>Well, Today i am gonna show you how can create JSON structures of one to one , one to many and many to many relationships .</p><p>Let’s Begin.</p><p>SQL provides 2 functions named <strong>JSON_ARRAYAGG </strong>And <strong>JSON_OBJECT </strong>and these functions can make our life a hell lot easier see the comparisons below of with using SQL functions and without using SQL functions.</p><p>This is a many to many relationship between product and tags and would look like this and this is what we want to achieve:</p><p>Now let’s see the comparisons how we can achieve this results both on code level and SQL level .</p><pre>[<br>    {<br>        &quot;id&quot;: 1,<br>        &quot;name&quot;: &quot;Marvel Tshirt&quot;,<br>        &quot;created_at&quot;: null,<br>        &quot;updated_at&quot;: null,<br>        &quot;tags&quot;: [<br>            {<br>                &quot;id&quot;: 4,<br>                &quot;name&quot;: &quot;Avengers&quot;<br>            },<br>            {<br>                &quot;id&quot;: 3,<br>                &quot;name&quot;: &quot;Red Color&quot;<br>            },<br>            {<br>                &quot;id&quot;: 5,<br>                &quot;name&quot;: &quot;Tshirt&quot;<br>            }<br>        ]<br>    },<br>    {<br>        &quot;id&quot;: 2,<br>        &quot;name&quot;: &quot;Roadster Full sleves tshirt&quot;,<br>        &quot;created_at&quot;: null,<br>        &quot;updated_at&quot;: null,<br>        &quot;tags&quot;: [<br>            {<br>                &quot;id&quot;: 3,<br>                &quot;name&quot;: &quot;Red Color&quot;<br>            },<br>            {<br>                &quot;id&quot;: 2,<br>                &quot;name&quot;: &quot;Full Sleeves&quot;<br>            }<br>        ]<br>    }<br>]</pre><p>Code Level Grouping (Even pagination won’t work here)</p><pre>/** <br>*     many to many relationship example<br>      product -&gt; tags<br>      tag -&gt; products<br>*/<br><br>$sql1 = &quot;SELECT products.id,products.name as product_name,tags.id as tag_id ,tags.name as tag_name FROM products<br>        LEFT JOIN product_tag ON product_tag.product_id = products.id<br>        LEFT JOIN tags ON product_tag.tag_id = tags.id<br>    &quot;; <br>$results = \DB::select($sql1);<br>  foreach($results as $result)<br>  {<br>      if (!isset($data[$result-&gt;id])) {<br>      <br>          $data[$result-&gt;id] = [<br>              &#39;name&#39; =&gt; $result-&gt;product_name,<br>              &#39;tags&#39; =&gt; []<br>          ];<br>      }<br>      $data[$result-&gt;id][&#39;tags&#39;][] = $result-&gt;tag_name;<br>  }<br>return array_values($data);</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/426/0*7Mzg5YXIyKpiRGi0.png" /></figure><p>The 1st SQL Will give us the result as follows.</p><p>You could simply do this: (SQL LEVEL Grouping ) <br>Best part : pagination will work !</p><pre>$sql1 = &quot;SELECT products.*,<br>    (<br>        SELECT <br>            JSON_ARRAYAGG(<br>                JSON_OBJECT(<br>                    &#39;id&#39;, tags.id,<br>                    &#39;name&#39;, tags.name<br>                )<br>            )<br>        FROM product_tag<br>        LEFT JOIN tags ON product_tag.tag_id = tags.id<br>        WHERE product_tag.product_id = products.id<br><br>    ) AS tags<br>FROM products&quot;;<br>$results = \DB::select($sql1);<br>foreach ($results as &amp;$result) {<br>    <br>    $result-&gt;tags = json_decode($result-&gt;tags);<br>}<br>return $results;<br></pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/982/0*9MxaOQkOiAl4sVhl.png" /></figure><p>2nd SQL Result will be printed like this :</p><p>as you can see in the above image all our tags information is now in JSON.</p><p>Now let’s understand first what is the difference between <strong>JSON_OBJECT </strong>and <strong>JSON_ARRAYAGG</strong></p><blockquote><strong>JSON_OBJECT </strong>is a SQL function used to create JSON objects from key-value pairs. It allows us to generate JSON data directly within SQL queries and will give you only a JSON Object. Now in order to collect multiple json objects you would need JSON_ARRAYAGG .</blockquote><blockquote><strong>JSON_ARRAYAGG </strong>collects values from multiple rows or a set of individual json objects and combines them into a single JSON array .</blockquote><p>Let’s dive a little deep with the SQL :</p><pre>// THE SQL<br>SELECT products.*,<br>(<br>    SELECT <br>        JSON_ARRAYAGG(<br>            JSON_OBJECT(<br>                &#39;id&#39;, tags.id,<br>                &#39;name&#39;, tags.name<br>            )<br>        )<br>    FROM product_tag<br>    LEFT JOIN tags ON product_tag.tag_id = tags.id<br>    WHERE product_tag.product_id = products.id<br>) AS tags<br>FROM products</pre><ol><li><strong>Outer SELECT Clause:</strong></li></ol><p>We start with a SELECT statement, retrieving all columns from the “products” table.</p><p><strong>2. (Subquery part):</strong></p><p>Within the outer SELECT statement, there’s a subquery which will retrieve tags associated with each product.</p><ol><li><strong>JSON_ARRAYAGG and JSON_OBJECT Functions ( for structuring JSON):</strong></li></ol><ul><li>Inside the subquery, <strong>JSON_ARRAYAGG </strong>is used to collect multiple tags of the products or you can say a set individual JSON objects.</li><li><strong>JSON_OBJECT </strong>is used to structure our JSON objects with key and value pairs (‘id’ and ‘name’) and here you have to mention the values that you actually want from the tags table. The syntax you can look in the above code, you just have to separate the keys by comma.</li></ul><p><strong>2. JOIN and WHERE Clauses (The actual Logic):</strong></p><blockquote>Note that without this logic it wont work:</blockquote><ul><li>Now there is not much difference in the logic. Whatever you wrote in the previous query will be now shifted inside the subquery so instead of joining “<strong><em>product_tag” </em></strong>with the “<strong><em>products” </em></strong>table , you will now select the records from the <strong><em>“product_tag” </em></strong>table and join it with the <strong><em>“tags” </em></strong>table to retrieve the tags information.</li><li>And the where clause will filters records based on the condition that “<strong><em>product_id</em></strong>” matches the “<strong><em>id</em></strong>” of products from the outer query.<br>which will give us the the products associated with tags</li><li>and finally we will join it with the tags table <br>where “<strong><em>product_tag.tag_id = </em></strong><a href="http://tags.id/"><strong><em>tags.id</em></strong></a><strong><em>” </em></strong><em>, </em>which will give us the information of the <strong><em>tags </em></strong>table .</li></ul><pre>// BEFORE<br>SELECT <br>        products.id,products.name as product_name,<br>        tags.id as tag_id ,tags.name as tag_name <br>FROM products<br>    LEFT JOIN product_tag ON product_tag.product_id = products.id<br>    LEFT JOIN tags ON product_tag.tag_id = tags.id;<br><br>// AFTER<br>SELECT products.*,<br>(<br>    SELECT <br>        JSON_ARRAYAGG(<br>            JSON_OBJECT(<br>                &#39;id&#39;, tags.id,<br>                &#39;name&#39;, tags.name<br>            )<br>        )<br>    FROM product_tag <br>    LEFT JOIN tags ON product_tag.tag_id = tags.id<br>    WHERE product_tag.product_id = products.id<br>) AS tags<br>FROM products</pre><p>3. Alias:</p><ul><li>The JSON array generated by the subquery has to be aliased for eg:- as <strong><em>“tags”</em></strong></li></ul><h4>PHP side:</h4><p>Here you just have to decode the JSON array like this:</p><pre>$results = \DB::select($sql1);<br><br>foreach ($results as &amp;$result) {<br>    <br>    $result-&gt;tags = json_decode($result-&gt;tags);<br>}<br>return $results;</pre><p>which will output the below JSON .</p><pre>[<br>    {<br>        &quot;id&quot;: 1,<br>        &quot;name&quot;: &quot;Marvel Tshirt&quot;,<br>        &quot;created_at&quot;: null,<br>        &quot;updated_at&quot;: null,<br>        &quot;tags&quot;: [<br>            {<br>                &quot;id&quot;: 4,<br>                &quot;name&quot;: &quot;Avengers&quot;<br>            },<br>            {<br>                &quot;id&quot;: 3,<br>                &quot;name&quot;: &quot;Red Color&quot;<br>            },<br>            {<br>                &quot;id&quot;: 5,<br>                &quot;name&quot;: &quot;Tshirt&quot;<br>            }<br>        ]<br>    },<br>    {<br>        &quot;id&quot;: 2,<br>        &quot;name&quot;: &quot;Roadster Full sleves tshirt&quot;,<br>        &quot;created_at&quot;: null,<br>        &quot;updated_at&quot;: null,<br>        &quot;tags&quot;: [<br>            {<br>                &quot;id&quot;: 3,<br>                &quot;name&quot;: &quot;Red Color&quot;<br>            },<br>            {<br>                &quot;id&quot;: 2,<br>                &quot;name&quot;: &quot;Full Sleeves&quot;<br>            }<br>        ]<br>    }<br>]</pre><p>I have listed some other examples of 1:1 &amp; 1:Many structuring JSON in SQL</p><p><strong>1 to 1 Example: (User has One Product | Product belongs to a User )</strong></p><blockquote>Note: No need to write <strong>JSON_ARRAYGG </strong>here because we don’t want a list right we just want an object so <strong>JSON_OBJECT </strong>.</blockquote><pre>$sql1 = &quot;SELECT products.id, products.name,<br>      (<br>          SELECT <br>              JSON_OBJECT(<br>                  &#39;id&#39;, users.id,<br>                  &#39;name&#39;, users.name,<br>                  &#39;email&#39;, users.email<br>              )<br>          FROM users<br>          WHERE users.id = products.user_id<br>) AS users<br>FROM products&quot;;<br><br>$results = \DB::select($sql1);</pre><p>Output:</p><pre>[<br>    {<br>        &quot;id&quot;: 1,<br>        &quot;name&quot;: &quot;Marvel Tshirt&quot;,<br>        &quot;users&quot;: {<br>            &quot;id&quot;: 1,<br>            &quot;name&quot;: &quot;John Doe&quot;,<br>            &quot;email&quot;: &quot;johndoe11@gmail.com&quot;<br>        }<br>    },<br>    {<br>        &quot;id&quot;: 2,<br>        &quot;name&quot;: &quot;Roadster Full sleves tshirt&quot;,<br>        &quot;users&quot;: {<br>            &quot;id&quot;: 2,<br>            &quot;name&quot;: &quot;Richard Parker&quot;,<br>            &quot;email&quot;: &quot;richard88@gmail.com&quot;<br>        }<br>    }<br>]</pre><p><strong>1 to many example: (User has many Products | Product Belongs to User)</strong></p><pre>$sql1 = &quot;SELECT users.id, users.name,users.email,<br>    (<br>        SELECT <br>            JSON_ARRAYAGG(<br>                JSON_OBJECT(<br>                    &#39;id&#39;, products.id,<br>                    &#39;name&#39;, products.name<br>                )<br>            )<br>        FROM products<br>        WHERE products.user_id = users.id<br>) AS products<br>FROM users&quot;;<br><br>$results = \DB::select($sql1);<br></pre><p>Output</p><pre>[<br>    {<br>        &quot;id&quot;: 1,<br>        &quot;name&quot;: &quot;John Doe&quot;,<br>        &quot;email&quot;: &quot;johndoe11@gmail.com&quot;,<br>        &quot;products&quot;: [<br>            {<br>                &quot;id&quot;: 1,<br>                &quot;name&quot;: &quot;Marvel Tshirt&quot;<br>            },<br>            {<br>                &quot;id&quot;: 3,<br>                &quot;name&quot;: &quot;Hoodies&quot;<br>            }<br>        ]<br>    },<br>    {<br>        &quot;id&quot;: 2,<br>        &quot;name&quot;: &quot;Richard Parker&quot;,<br>        &quot;email&quot;: &quot;richard88@gmail.com&quot;,<br>        &quot;products&quot;: [<br>            {<br>                &quot;id&quot;: 2,<br>                &quot;name&quot;: &quot;Roadster Full sleves tshirt&quot;<br>            }<br>        ]<br>    }<br>]</pre><p>All Examples are given here in this repository so you can refer to it !</p><p><a href="https://github.com/CODE-AXION/RAW_SQL_Json_Structures_Examples">GitHub - CODE-AXION/RAW_SQL_Json_Structures_Examples: Set of JSON_ARRAYAGG &amp; JSON_OBJECT SQL Examples</a></p><blockquote>Thank you for reading this article ! and i hope you learned something new !</blockquote><p><em>Happy Coding …</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=63fd122cfaac" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Livewire 3: prevent Livewire for loading in every page while keeping Alpine functional]]></title>
            <link>https://medium.com/@codeaxion77/livewire-3-prevent-livewire-for-loading-in-every-page-while-keeping-alpine-functional-2be04fa245f6?source=rss-c43ba02a17a3------2</link>
            <guid isPermaLink="false">https://medium.com/p/2be04fa245f6</guid>
            <category><![CDATA[livewire]]></category>
            <category><![CDATA[laravel-livewire]]></category>
            <category><![CDATA[laravel]]></category>
            <category><![CDATA[alpine]]></category>
            <category><![CDATA[laravel-framework]]></category>
            <dc:creator><![CDATA[Code Axion The Security Breach]]></dc:creator>
            <pubDate>Sun, 31 Dec 2023 18:30:57 GMT</pubDate>
            <atom:updated>2023-12-31T18:30:57.831Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/741/1*KCMIxnXhKXzRATSglpScRg.png" /></figure><p>So livewire 3 is here and I just upgraded by version yesterday and took me hour to fix the breaking changes and while making changes I noticed that it automatically injects alpine and livewire scripts in every page.</p><p>Well I referred to the docs and all and I saw that livewire has to be injected in every page and I was like why so , it will be huge headache in performance and even in my website I am only using livewire for 1 page which is ecommerce shop page filter and I don’t want to include livewire scripts in every page .</p><blockquote>I searched online , went to GitHub issues and found nothing …</blockquote><p>I figured how bout we only include alpine scripts in normal pages and livewire scripts in livewire page along with alpine functioning .</p><p>Let me show you !</p><p>If you see if it was that simple we could use import like this :</p><pre>if($condition)<br>{<br>     import Alpine from &#39;alpinejs&#39;<br><br>     // YOUR ALPINE JS CODE<br><br>     Alpine.start()<br>}</pre><p>but this wont work so we have to use dynamic imports , I bet you might not have heard about this but its kinda cool ! !</p><p>The import(module) expression loads the module and returns a promise that resolves into a module object that contains all its exports. It can be called from any place in the code.</p><p>We can use it dynamically in any place of the code, for instance:</p><pre>let modulePath = prompt(&quot;Which module to load?&quot;);<br><br>import(modulePath)<br>  .then(obj =&gt; &lt;module object&gt;)<br>  .catch(err =&gt; &lt;loading error, e.g. if no such module&gt;)</pre><p>so in our case it would be :</p><p>BEFORE:</p><pre>APP.JS<br><br>require(&#39;./bootstrap&#39;);<br><br>import Alpine from &#39;alpinejs&#39;;<br><br>window.Alpine = Alpine;<br>let csrfToken = document.querySelector(&#39;meta[name=&quot;csrf-token&quot;]&#39;).getAttribute(&#39;content&#39;);<br>    <br>Alpine.store(&#39;cartSettings&#39;, {}) // &lt;-- YOUR ALPINE JS CODE<br><br>Alpine.start();</pre><p>AFTER:</p><pre>APP.JS<br><br>require(&#39;./bootstrap&#39;);<br><br>let csrfToken = document.querySelector(&#39;meta[name=&quot;csrf-token&quot;]&#39;).getAttribute(&#39;content&#39;);<br><br>if(!route().current(&#39;shop.page&#39;))<br>{<br>    import(&#39;alpinejs&#39;).then((module) =&gt; {<br>        window.Alpine = module.default<br>        Alpine.store(&#39;cartSettings&#39;, {}) // &lt;-- YOUR ALPINE JS CODE<br>        Alpine.start();<br>    });<br>}else{<br>    <br>    Alpine.store(&#39;cartSettings&#39;, {}) // &lt;-- YOUR ALPINE JS CODE<br>}<br></pre><p>and the view that you would be using LIVEWIRE 3 Component:</p><blockquote><strong>resources/views/shop-page.blade.php</strong></blockquote><blockquote>shop-page.blade.php</blockquote><pre>&lt;x-app-layout&gt;<br><br>  LIVEWIRE COMPONENT --&gt; @livewire(&#39;shop-page-component&#39;,[&#39;filter_type&#39;=&gt;$filter_type,&#39;filter_slug&#39; =&gt;$filter_slug , &#39;filter_id&#39; =&gt; $filter_id, &#39;category&#39; =&gt; $category ?? false])<br><br>    @push(&#39;styles&#39;) <br>        @livewireStyles<br>    @endpush<br><br>    @push(&#39;scripts&#39;)<br>        @livewireScripts<br>    @endpush<br><br>&lt;/x-app-layout&gt;</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2be04fa245f6" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Don’t Use JSON Columns in MySQL Here’s Why !]]></title>
            <link>https://medium.com/@codeaxion77/dont-use-json-columns-in-mysql-here-s-why-efbb82aafffd?source=rss-c43ba02a17a3------2</link>
            <guid isPermaLink="false">https://medium.com/p/efbb82aafffd</guid>
            <category><![CDATA[database-design]]></category>
            <category><![CDATA[database-normalization]]></category>
            <category><![CDATA[rdbms]]></category>
            <category><![CDATA[json]]></category>
            <category><![CDATA[relational-databases]]></category>
            <dc:creator><![CDATA[Code Axion The Security Breach]]></dc:creator>
            <pubDate>Fri, 12 May 2023 10:25:36 GMT</pubDate>
            <atom:updated>2026-02-05T09:09:56.826Z</atom:updated>
            <content:encoded><![CDATA[<h3>Don’t Use JSON Columns in MySQL Here’s Why !</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*D4f8cDnO-acIn4uj.jpg" /></figure><p>Do not store data in JSON, use columns, this is why they are there.</p><p>You are using relational database to store your data, use the features what those softwares are providing to store and organize your data.</p><p>Storing values in their separate columns, allows you to perform different aggregations, filtering on those columns without the overhead of parsing a non-relational data structure (most probably using a third party plugin/clr/function/whatever).</p><p>Additionally JSON data has no fixed structure. You can not verify the consistency of the data stored in the JSON field without parsing the field and writing custom validations.</p><p>It maybe easy to store data with variable or complex structure, but it comes at a cost.</p><p>Queries against JSON data are more complex than traditional SQL queries against normal rows and columns. As i said It’s harder to learn to search or sort data stored in JSON. Not impossible — but it’s a totally different type of query. If you don’t have experience with this yet, you will experience a steep learning curve.</p><p>Storing multiple data in one field also means, <strong>you can not (or not easy to)</strong></p><ul><li>use constraints on the embedded fields</li><li>you can not enforce the structure, valid ranges, valid values for each fields for the embedded fields</li><li>define the data type of the embedded fields</li><li>index the data</li><li>aggregate/search in those fields</li><li>scale the system</li><li>Normalize your data model and everything will be more efficient (alot of people ignore this)</li></ul><p><strong>The database server can not</strong></p><ul><li>keep track of index statistics for each fields</li><li>optimize queries using the JSON field (because of the string manipulations required to extract data)</li><li>can not store the data for each field optimally.</li></ul><p>The above things are important, but none of the lists are complete.</p><p><strong>What will you win?</strong></p><ul><li>Some field names.</li><li>Some flexibility in the database, but much more complex functions in the application, because all the validations should be done in the application twice — when you want to write and when you are reading the data.</li><li>A huge headache when you have to fix something in the JSON field.</li></ul><p>As a note: the format you choose for storing the data is opinion based of course, but as a rule of thumb, use traditional columns whenever they can satisfy your needs and avoid using serialized data. Especially if you want to use only some parts of it for any kind of calculation.</p><p>And if it comes to performance you have designed indexes well to support your queries, MySQL can handle hundreds of millions of rows per table. Tables typically start to get hard to scale when you have over 1 billion (1e9) rows.</p><p><strong>When can you store serialized data:</strong> When it is not important to enforce the consistency and you will NEVER use it for statistical queries or for filtering. (However, in most cases, the never part is not true :))</p><p>Use JSON if you have information that is rarely changed, or if your application expects JSON. In this case you will optimize read and load performance.</p><p>Thank You For Reading this Article<strong> !</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=efbb82aafffd" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Supercharge Your Laravel App with Spatie Roles and Permissions .]]></title>
            <link>https://medium.com/@codeaxion77/supercharge-your-laravel-app-with-spatie-roles-and-permissions-f20fe02a8c75?source=rss-c43ba02a17a3------2</link>
            <guid isPermaLink="false">https://medium.com/p/f20fe02a8c75</guid>
            <category><![CDATA[php]]></category>
            <category><![CDATA[laravel-framework]]></category>
            <category><![CDATA[spatie]]></category>
            <category><![CDATA[authorization]]></category>
            <category><![CDATA[laravel]]></category>
            <dc:creator><![CDATA[Code Axion The Security Breach]]></dc:creator>
            <pubDate>Sun, 09 Apr 2023 13:22:51 GMT</pubDate>
            <atom:updated>2023-04-09T14:22:58.146Z</atom:updated>
            <content:encoded><![CDATA[<h3>Supercharge Your Laravel App with Spatie Roles and Permissions .</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*w63QNF7wLKhRqasBvhkGMw.png" /></figure><blockquote>In This Article I have Described How You Can Handle Authorization With Spatie Permission Package And Give Permissions To Different Roles And Restrict Certain Areas And Features With Laravel Authorization Methods</blockquote><p>And Believe me its really <em>easy peasy</em> …</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/320/0*0L-14eqsKjwy87WG.gif" /></figure><p><strong>Lets do the Installation and stuffs</strong></p><p>Install the<strong> Spatie Permission Package</strong> with these commands :</p><pre>//Install the package<br> composer require spatie/laravel-permission<br><br>//Register the provider in the config/app.php<br>&#39;providers&#39; =&gt; [<br>    // ...<br>    Spatie\Permission\PermissionServiceProvider::class,<br>];<br><br>//This will generate the necessary migrations for the package and the config file <br>php artisan vendor:publish --provider=&quot;Spatie\Permission\PermissionServiceProvider&quot;<br><br><br>php artisan optimize:clear<br># or<br>php artisan config:clear<br><br><br>php artisan migrate // will migrate the neccessary tables required for this package</pre><p>User Model Should Have HasRole Trait:</p><pre><br>use Illuminate\Foundation\Auth\User as Authenticatable;<br>use Spatie\Permission\Traits\HasRoles;<br><br>class User extends Authenticatable<br>{<br>    use HasRoles;<br><br>    // ...<br>}</pre><p>Now we are gonna create some permissions in the <strong>permissions </strong>table .</p><p><strong>Imp: </strong>Make Sure To First Add The “<strong> MODULE Name</strong> “ With The<strong> DOT NOTATIO</strong>N And The OPERATION Name Like This<strong> :</strong></p><p><strong>Module Name</strong>: <em>categories</em><br><strong>Operation Name</strong>: <em>create</em></p><p><strong>Final</strong>: <em>categories.create</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*8nVMjEw4NkeEqbSW6Uqdww.png" /></figure><p>This is gonna help to display the “<strong>add permissions to roles ” </strong>settings category wise like this :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xWmfEkMKUuZXe7Ds97PNFA.png" /></figure><p>Now lets create the <strong>RoleController </strong>with the “ <em>php artisan make:controller RoleController “ </em>command. We don’t need to create the model for roles or permissions as we already have it in our package and we can use them with “<strong>use Spatie\Permission\Models\Role </strong>”. Lets create some methods for our Role controller .</p><pre>&lt;?php<br><br>namespace App\Http\Controllers;<br><br>use Illuminate\Http\Request;<br><br>use Spatie\Permission\Models\Role; &lt;--- ROLE MODEL<br>use Spatie\Permission\Models\Permission; &lt;---- PERMISSION MODEL<br><br>class RoleController extends Controller<br>{<br>    public function allRoles()<br>    {<br>    <br>    }<br><br>    public function create()<br>    {<br>    <br>    }<br><br>    public function store(Request $request)<br>    {<br>    <br>    }<br><br>    public function edit($id)<br>    {<br>    <br>    }<br><br>    public function update(Request $request, $id)<br>    {<br><br>    }<br><br>    public function delete($id)<br>    {<br>    <br>    }<br><br>}</pre><p>Lets take a look at create roles page and how to display it like this :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*43JXhK2__svOSnobxroB7A.png" /></figure><p><strong>Create method :</strong></p><pre>public function create()<br>{<br>    \DB::statement(&quot;SET SQL_MODE=&#39;&#39;&quot;);;<br>    $role_permission = Permission::select(&#39;name&#39;,&#39;id&#39;)-&gt;groupBy(&#39;name&#39;)-&gt;get();<br><br>    $custom_permission = array();<br><br>    foreach($role_permission as $per){<br><br>        $key = substr($per-&gt;name, 0, strpos($per-&gt;name, &quot;.&quot;));<br><br>        if(str_starts_with($per-&gt;name, $key)){<br>         <br>            $custom_permission[$key][] = $per;<br>        }<br><br>    }<br> <br>    return view(&#39;admin.roles.create&#39;)-&gt;with(&#39;permissions&#39;,$custom_permission);<br>}</pre><p>Take a look at how we are gonna create this array:</p><ol><li>$role_permission = Permission::select(&#39;name&#39;,&#39;id&#39;)-&gt;groupBy(&#39;name&#39;)-&gt;get();:This selects only the name and id columns from the permissions table, and groups the results by the name column and finally, it fetches all the results :</li></ol><p>Example :-</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/271/1*25oBZVEuXoxtSdFHqDxpKg.png" /></figure><p>2. $custom_permission = array();: This initializes an empty array called $custom_permission which will be used to store custom permissions later in the code.</p><pre>   foreach($role_permission as $per){<br><br>        $key = substr($per-&gt;name, 0, strpos($per-&gt;name, &quot;.&quot;));<br><br>        if(str_starts_with($per-&gt;name, $key)){<br>            $custom_permission[$key][] = $per;<br>        }<br><br>    }</pre><p>3. $key = substr($per-&gt;name, 0, strpos($per-&gt;name, &quot;.&quot;));: This line extracts the substring from the beginning of the name field of the current $per item, up to the first occurrence of a period (&quot;.&quot;) character. This is done using the substr() and strpos() functions in PHP, and the resulting substring is stored as the $key .</p><p>4. if(str_starts_with($per-&gt;name, $key)){ ... }: It then checks if the ‘name’ column string starts with the extracted $key using the str_starts_with() function. eg:- like this :</p><pre>if categories.create starts with categories which is true <br>   (categories == categories.create) ==&gt; true</pre><pre>Some defination of str_starts_with.<br><br>str_starts_with($string, $substring) <br>Parameters:<br><br>$string: This parameter refers to the string whose starting string needs to be checked.<br>$substring: This parameter refers to the string that needs to be checked.<br><br>Return Type: If the string begins with the substring then str_starts_with() will return TRUE otherwise it will return FALSE.  </pre><p>5. If it does, it proceeds to add the record to the $custom_permission array using $key as the array key which is the categories and the $per as the object.</p><p>So it will look like this :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/509/1*0hTf_L4B9Y5FA5aCuj5vkQ.png" /></figure><p>This is used as a grouping mechanism to group permissions with similar prefixes together in the $custom_permission array.</p><p>We can access the $custom_permission array and can use it to display custom permissions grouped by their prefixes.</p><p>Now lets display this in view</p><p><strong>create.blade.php:</strong></p><pre>&lt;div class=&quot;ml-4 mt-16 w-9/12&quot;&gt;<br>  &lt;form action=&quot;{{route(&#39;roles.store&#39;)}}&quot; method=&quot;POST&quot;&gt;<br>      @csrf<br>  <br>      &lt;h1 class=&quot;text-3xl mt-4 mb-8&quot;&gt; Create Role &lt;/h1&gt;<br><br>      &lt;div class=&quot;mb-6&quot;&gt;<br>          &lt;label for=&quot;text&quot; class=&quot;block mb-2 text-sm font-medium text-gray-900 dark:text-white&quot;&gt;Role Name&lt;/label&gt;<br>          &lt;input type=&quot;text&quot; value=&quot;{{old(&#39;name&#39;)}}&quot; name=&quot;name&quot; id=&quot;email&quot; class=&quot;bg-gray-50 w-80 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 &quot; placeholder=&quot;User, Editor, Author ... &quot; &gt;<br>          <br>          @foreach ($errors-&gt;get(&#39;name&#39;) as $error)<br>              &lt;p class=&quot;text-red-600&quot;&gt;{{$error}}&lt;/p&gt;<br>          @endforeach<br>      &lt;/div&gt;<br><br>      &lt;table class=&quot;permissionTable border rounded-md bg-white overflow-hidden shadow-lg my-4 p-4&quot;&gt;<br>          &lt;th class=&quot;px-4 py-4&quot;&gt;<br>              {{__(&#39;Section&#39;)}}<br>          &lt;/th&gt;<br><br>          &lt;th class=&quot;px-4 py-4&quot;&gt;<br>              &lt;label&gt;<br>                  &lt;input class=&quot;grand_selectall&quot; type=&quot;checkbox&quot;&gt;<br>                  {{__(&#39;Select All&#39;) }}<br>              &lt;/label&gt;<br>          &lt;/th&gt;<br><br>          &lt;th class=&quot;px-4 py-4&quot;&gt;<br>              {{__(&quot;Available permissions&quot;)}}<br>          &lt;/th&gt;<br><br><br><br>          &lt;tbody&gt;<br>          @foreach($permissions as $key =&gt; $group)<br>              &lt;tr class=&quot;py-8&quot;&gt;<br>                  &lt;td class=&quot;p-6&quot;&gt;<br>                      &lt;b&gt;{{ ucfirst($key) }}&lt;/b&gt;<br>                  &lt;/td&gt;<br>                  &lt;td class=&quot;p-6&quot; width=&quot;30%&quot;&gt;<br>                      &lt;label&gt;<br>                          &lt;input class=&quot;selectall&quot; type=&quot;checkbox&quot;&gt;<br>                          {{__(&#39;Select All&#39;) }}<br>                      &lt;/label&gt;<br>                  &lt;/td&gt;<br>                  &lt;td class=&quot;p-6&quot;&gt;<br><br>                      @forelse($group as $permission)<br><br>                      &lt;label style=&quot;width: 30%&quot; class=&quot;&quot;&gt;<br>                          &lt;input name=&quot;permissions[]&quot; class=&quot;permissioncheckbox&quot; class=&quot;rounded-md border&quot; type=&quot;checkbox&quot; value=&quot;{{ $permission-&gt;id }}&quot;&gt;<br>                          {{$permission-&gt;name}} &amp;nbsp;&amp;nbsp;<br>                      &lt;/label&gt;<br><br>                      @empty<br>                          {{ __(&quot;No permission in this group !&quot;) }}<br>                      @endforelse<br><br>                  &lt;/td&gt;<br><br>              &lt;/tr&gt;<br>          @endforeach<br>          &lt;/tbody&gt;<br>      &lt;/table&gt;<br><br><br>      &lt;button type=&quot;submit&quot; class=&quot;text-white bg-gradient-to-r from-blue-500 via-blue-600 to-blue-700 hover:bg-gradient-to-br focus:ring-4 focus:outline-none focus:ring-blue-300 dark:focus:ring-blue-800 shadow-lg shadow-blue-500/50 dark:shadow-lg dark:shadow-blue-800/80 font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-2 mb-2 &quot;&gt;<br>          Create Role<br>      &lt;/button&gt;<br><br>  &lt;/form&gt;<br>&lt;/div&gt;</pre><p>Now in order to get the <strong>select all </strong>feature working paste this code inside script tag in create.blade.php:</p><pre><br><br>$(&quot;.permissionTable&quot;).on(&#39;click&#39;, &#39;.selectall&#39;, function () {<br><br>    if ($(this).is(&#39;:checked&#39;)) {<br>        $(this).closest(&#39;tr&#39;).find(&#39;[type=checkbox]&#39;).prop(&#39;checked&#39;, true);<br><br>    } else {<br>        $(this).closest(&#39;tr&#39;).find(&#39;[type=checkbox]&#39;).prop(&#39;checked&#39;, false);<br><br>    }<br><br>    calcu_allchkbox();<br><br>});<br><br>$(&quot;.permissionTable&quot;).on(&#39;click&#39;, &#39;.grand_selectall&#39;, function () {<br>    if ($(this).is(&#39;:checked&#39;)) {<br>        $(&#39;.selectall&#39;).prop(&#39;checked&#39;, true);<br>        $(&#39;.permissioncheckbox&#39;).prop(&#39;checked&#39;, true);<br>    } else {<br>        $(&#39;.selectall&#39;).prop(&#39;checked&#39;, false);<br>        $(&#39;.permissioncheckbox&#39;).prop(&#39;checked&#39;, false);<br>    }<br>});<br><br>$(function () {<br><br>    calcu_allchkbox();<br>    selectall();<br><br>});<br><br>function selectall(){<br><br>    $(&#39;.selectall&#39;).each(function (i) {<br><br>        var allchecked = new Array();<br><br>        $(this).closest(&#39;tr&#39;).find(&#39;.permissioncheckbox&#39;).each(function (index) {<br>            if ($(this).is(&quot;:checked&quot;)) {<br>                allchecked.push(1);<br>            } else {<br>                allchecked.push(0);<br>            }<br>        });<br><br>        if ($.inArray(0, allchecked) != -1) {<br>            $(this).prop(&#39;checked&#39;, false);<br>        } else {<br>            $(this).prop(&#39;checked&#39;, true);<br>        }<br><br>    });<br>}<br><br>function calcu_allchkbox(){<br><br>    var allchecked = new Array();<br><br>    $(&#39;.selectall&#39;).each(function (i) {<br><br><br>        $(this).closest(&#39;tr&#39;).find(&#39;.permissioncheckbox&#39;).each(function (index) {<br>            if ($(this).is(&quot;:checked&quot;)) {<br>                allchecked.push(1);<br>            } else {<br>                allchecked.push(0);<br>            }<br>        });<br><br><br>    });<br><br>    if ($.inArray(0, allchecked) != -1) {<br>        $(&#39;.grand_selectall&#39;).prop(&#39;checked&#39;, false);<br>    } else {<br>        $(&#39;.grand_selectall&#39;).prop(&#39;checked&#39;, true);<br>    }<br><br>}<br><br><br><br>$(&#39;.permissionTable&#39;).on(&#39;click&#39;, &#39;.permissioncheckbox&#39;, function () {<br><br>    var allchecked = new Array;<br><br>    $(this).closest(&#39;tr&#39;).find(&#39;.permissioncheckbox&#39;).each(function (index) {<br>        if ($(this).is(&quot;:checked&quot;)) {<br>            allchecked.push(1);<br>        } else {<br>            allchecked.push(0);<br>        }<br>    });<br><br>    if ($.inArray(0, allchecked) != -1) {<br>        $(this).closest(&#39;tr&#39;).find(&#39;.selectall&#39;).prop(&#39;checked&#39;, false);<br>    } else {<br>        $(this).closest(&#39;tr&#39;).find(&#39;.selectall&#39;).prop(&#39;checked&#39;, true);<br><br>    }<br><br>    calcu_allchkbox();<br><br>});</pre><p><strong>Store method :</strong></p><p>Now we will create the role method and we will attach the permissions to the roles using <strong>givePermissionTo()</strong> method .</p><pre>public function store(Request $request)<br>{<br>    $request-&gt;validate([<br><br>        &#39;name&#39; =&gt; &#39;required&#39;,<br>    ]);<br><br>    $role = Role::create([<br>        &#39;name&#39; =&gt; $request-&gt;name,<br>    ]);<br><br>    if($request-&gt;permissions){<br><br>        foreach ($request-&gt;permissions as $key =&gt; $value) {<br>            $role-&gt;givePermissionTo($value);<br>        }<br>    }<br><br>    return redirect()-&gt;route(&#39;roles.all&#39;);<br>}</pre><p><strong>Edit Method:</strong></p><pre> public function edit($id)<br>    {<br>       <br>        $role = Role::with(&#39;permissions&#39;)-&gt;find($id);<br><br>        \DB::statement(&quot;SET SQL_MODE=&#39;&#39;&quot;);<br>        $role_permission = Permission::select(&#39;name&#39;,&#39;id&#39;)-&gt;groupBy(&#39;name&#39;)-&gt;get();<br><br><br>        $custom_permission = array();<br><br>        foreach($role_permission as $per){<br><br>            $key = substr($per-&gt;name, 0, strpos($per-&gt;name, &quot;.&quot;));<br><br>            if(str_starts_with($per-&gt;name, $key)){<br>                $custom_permission[$key][] = $per;<br>            }<br><br>        }<br><br>        return view(&#39;admin.roles.edit&#39;,compact(&#39;role&#39;))-&gt;with(&#39;permissions&#39;,$custom_permission);<br>    }</pre><p><strong>edit.blade.php:</strong></p><pre>   &lt;div class=&quot;ml-4 mt-16 w-9/12&quot;&gt;<br>        &lt;form action=&quot;{{route(&#39;roles.store&#39;)}}&quot; method=&quot;POST&quot;&gt;<br>            @csrf<br>        <br>            &lt;h1 class=&quot;text-3xl mt-4 mb-8&quot;&gt; Update Role &lt;/h1&gt;<br><br>            &lt;div class=&quot;mb-6&quot;&gt;<br>                &lt;label for=&quot;text&quot; class=&quot;block mb-2 text-sm font-medium text-gray-900 dark:text-white&quot;&gt;Role Name&lt;/label&gt;<br>                &lt;input type=&quot;text&quot; value=&quot;{{old(&#39;name&#39;,$role-&gt;name ?? &#39;&#39;)}}&quot; name=&quot;name&quot; id=&quot;email&quot; class=&quot;bg-gray-50 w-80 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 &quot; placeholder=&quot;Wedding, Kitty kat, parties, lol deaths haha&quot; &gt;<br>                <br>                @foreach ($errors-&gt;get(&#39;name&#39;) as $error)<br>                    &lt;p class=&quot;text-red-600&quot;&gt;{{$error}}&lt;/p&gt;<br>                @endforeach<br>            &lt;/div&gt;<br><br>            &lt;table class=&quot;permissionTable border rounded-md bg-white overflow-hidden shadow-lg my-4 p-4&quot;&gt;<br>                &lt;th class=&quot;px-4 py-4&quot;&gt;<br>                    {{__(&#39;Section&#39;)}}<br>                &lt;/th&gt;<br><br>                &lt;th class=&quot;px-4 py-4&quot;&gt;<br>                    &lt;label&gt;<br>                        &lt;input class=&quot;grand_selectall&quot; type=&quot;checkbox&quot;&gt;<br>                        {{__(&#39;Select All&#39;) }}<br>                    &lt;/label&gt;<br>                &lt;/th&gt;<br><br>                &lt;th class=&quot;px-4 py-4&quot;&gt;<br>                    {{__(&quot;Available permissions&quot;)}}<br>                &lt;/th&gt;<br><br><br><br>                &lt;tbody&gt;<br>                @foreach($permissions as $key =&gt; $group)<br>                    &lt;tr class=&quot;py-8&quot;&gt;<br>                        &lt;td class=&quot;p-6&quot;&gt;<br>                            &lt;b&gt;{{ ucfirst($key) }}&lt;/b&gt;<br>                        &lt;/td&gt;<br>                        &lt;td class=&quot;p-6&quot; width=&quot;30%&quot;&gt;<br>                            &lt;label&gt;<br>                                &lt;input class=&quot;selectall&quot; type=&quot;checkbox&quot;&gt;<br>                                {{__(&#39;Select All&#39;) }}<br>                            &lt;/label&gt;<br>                        &lt;/td&gt;<br>                        &lt;td class=&quot;p-6&quot;&gt;<br><br>                            @forelse($group as $permission)<br><br>                            &lt;label style=&quot;width: 30%&quot; class=&quot;&quot;&gt;<br>                                &lt;input  {{ $role-&gt;permissions-&gt;contains(&#39;id&#39;,$permission-&gt;id) ? &quot;checked&quot; : &quot;&quot; }} name=&quot;permissions[]&quot; class=&quot;permissioncheckbox&quot; class=&quot;rounded-md border&quot; type=&quot;checkbox&quot; value=&quot;{{ $permission-&gt;id }}&quot;&gt;<br>                                {{$permission-&gt;name}} &amp;nbsp;&amp;nbsp;<br>                            &lt;/label&gt;<br><br>                            @empty<br>                                {{ __(&quot;No permission in this group !&quot;) }}<br>                            @endforelse<br><br>                        &lt;/td&gt;<br><br>                    &lt;/tr&gt;<br>                @endforeach<br>                &lt;/tbody&gt;<br>            &lt;/table&gt;<br><br><br>            &lt;button type=&quot;submit&quot; class=&quot;text-white bg-gradient-to-r from-blue-500 via-blue-600 to-blue-700 hover:bg-gradient-to-br focus:ring-4 focus:outline-none focus:ring-blue-300 dark:focus:ring-blue-800 shadow-lg shadow-blue-500/50 dark:shadow-lg dark:shadow-blue-800/80 font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-2 mb-2 &quot;&gt;<br>                Update Role<br>            &lt;/button&gt;<br>        &lt;/form&gt;<br>    &lt;/div&gt;</pre><p><strong>Update method :</strong></p><p>Multiple permissions can be synced to a role using <strong>syncPermissions </strong>method:</p><pre>public function update(Request $request, $id)<br>{<br>    <br>    $role = Role::where(&#39;id&#39;,$id)-&gt;first();<br><br>    $request-&gt;validate([<br>        &#39;name&#39; =&gt; &#39;required&#39;<br>    ]);<br><br>    $role-&gt;update([<br>        &quot;name&quot; =&gt; $request-&gt;name<br>    ]);<br><br>    $role-&gt;syncPermissions($request-&gt;permissions);<br><br><br>    return redirect()-&gt;route(&#39;admin.roles.all&#39;)-&gt;with(&#39;success&#39;,&#39;Roles Updated Successfully&#39;);<br>}</pre><p><strong>Delete method :</strong></p><pre>public function delete($id)<br>{<br>    $role = Role::where(&#39;id&#39;,$id)-&gt;first();<br><br>    if(isset($role)){<br>        <br>        $role-&gt;permissions()-&gt;detach();<br>        $role-&gt;delete();<br><br>        return redirect()-&gt;route(&#39;roles.all&#39;)-&gt;with(&#39;success&#39;,&#39;Roles Deleted Successfully&#39;);<br><br>    }<br>}</pre><p><strong>index.blade.php:</strong></p><pre>&lt;div class=&quot;flex flex-col mt-6&quot;&gt;<br>  &lt;div class=&quot;-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8&quot;&gt;<br>      &lt;div class=&quot;inline-block min-w-full py-2 align-middle md:px-6 lg:px-8&quot;&gt;<br>          &lt;div class=&quot;overflow-hidden border border-gray-200 dark:border-gray-700 md:rounded-lg&quot;&gt;<br>              &lt;table id=&quot;eventstable&quot; class=&quot;min-w-full divide-y divide-gray-200 dark:divide-gray-700&quot;&gt;<br>                  &lt;thead class=&quot;bg-gray-50 dark:bg-gray-800&quot;&gt;<br>                      &lt;tr&gt;<br>                          &lt;th scope=&quot;col&quot; class=&quot;py-3.5 px-4 text-sm font-normal text-left rtl:text-right text-gray-500 dark:text-gray-400&quot;&gt;<br>                              &lt;div class=&quot;flex items-center gap-x-3&quot;&gt;<br>                                  &lt;input type=&quot;checkbox&quot; class=&quot;text-blue-500 border-gray-300 rounded dark:bg-gray-900 dark:ring-offset-gray-900 dark:border-gray-700&quot;&gt;<br>                                  &lt;span&gt;Id&lt;/span&gt;<br>                              &lt;/div&gt;<br>                          &lt;/th&gt;<br><br>                          &lt;th scope=&quot;col&quot; class=&quot;px-12 py-3.5 text-sm font-normal text-left rtl:text-right text-gray-500 dark:text-gray-400&quot;&gt;<br>                              &lt;button class=&quot;flex items-center gap-x-2&quot;&gt;<br>                                  &lt;span&gt;Role Name&lt;/span&gt;<br>                              &lt;/button&gt;<br>                          &lt;/th&gt;<br><br>                          &lt;th scope=&quot;col&quot; class=&quot;px-4 py-3.5 text-sm font-normal text-left rtl:text-right text-gray-500 dark:text-gray-400&quot;&gt;<br>                              &lt;button class=&quot;flex items-center gap-x-2&quot;&gt;<br>                                  &lt;span&gt;Permissions&lt;/span&gt;<br>                              &lt;/button&gt;<br>                          &lt;/th&gt;<br><br><br>                          &lt;th scope=&quot;col&quot; class=&quot;relative py-3.5 px-4&quot;&gt;<br>                              &lt;span class=&quot;sr-only&quot;&gt;Edit&lt;/span&gt;<br>                          &lt;/th&gt;<br>                     <br>                      &lt;/tr&gt;<br>                  &lt;/thead&gt;<br>                  &lt;tbody class=&quot;bg-white divide-y divide-gray-200 dark:divide-gray-700 dark:bg-gray-900&quot;&gt;<br>                      <br>                      @foreach ($roles as $role)<br>                          <br>                      &lt;tr&gt;<br>                          &lt;td class=&quot;px-4 py-4 text-sm font-medium text-gray-700 whitespace-nowrap&quot;&gt;<br>                              &lt;div class=&quot;inline-flex items-center gap-x-3&quot;&gt;<br><br>                                  &lt;div class=&quot;flex items-center gap-x-2&quot;&gt;<br>                                      &lt;div&gt;<br>                                          &lt;h2 class=&quot;font-medium text-gray-800 dark:text-white &quot;&gt;{{$loop-&gt;iteration}}&lt;/h2&gt;<br>                                      &lt;/div&gt;<br>                                  &lt;/div&gt;<br>                              &lt;/div&gt;<br>                          &lt;/td&gt;<br>                          &lt;td class=&quot;px-4 py-4 text-sm text-gray-500 dark:text-gray-300 whitespace-nowrap&quot;&gt;{{$role-&gt;name}}&lt;/td&gt;<br>                          &lt;td class=&quot;px-4 py-4 text-sm text-gray-500 dark:text-gray-300 whitespace-nowrap&quot;&gt;<br>                              &lt;div class=&quot;flex items-center flex-wrap gap-2&quot;&gt;<br>                                  @foreach ($role-&gt;permissions as $permission)<br>                                      &lt;div class=&quot;rounded-full bg-indigo-400 px-2 py-0.5 text-indigo-200 font-semibold&quot;&gt;{{$permission-&gt;name}}&lt;/div&gt;<br>                                  @endforeach<br>                              &lt;/div&gt;<br>                          &lt;/td&gt;<br><br>                          <br>                          &lt;td class=&quot;px-4 py-4 text-sm whitespace-nowrap&quot;&gt;<br>                              &lt;div class=&quot;flex items-center gap-x-6&quot;&gt;<br><br>                                  &lt;a href=&quot;{{route(&#39;roles.edit&#39;,$role-&gt;id)}}&quot; class=&quot;block text-gray-500 transition-colors duration-200 dark:hover:text-yellow-500 dark:text-gray-300 hover:text-yellow-500 focus:outline-none&quot;&gt;<br>                                      &lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot; stroke-width=&quot;1.5&quot; stroke=&quot;currentColor&quot; class=&quot;w-5 h-5&quot;&gt;<br>                                          &lt;path stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot; d=&quot;M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10&quot; /&gt;<br>                                      &lt;/svg&gt;<br>                                  &lt;/a&gt;<br><br>                                  &lt;form method=&quot;POST&quot; action=&quot;{{route(&#39;roles.delete&#39;,$role-&gt;id)}}&quot;&gt;<br>                                      @csrf<br>                                      @method(&#39;DELETE&#39;)<br>                                      <br>                                      &lt;button type=&quot;submit&quot; class=&quot;text-gray-500 transition-colors duration-200 dark:hover:text-red-500 dark:text-gray-300 hover:text-red-500 focus:outline-none&quot;&gt;<br>                                          &lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; fill=&quot;none&quot; viewBox=&quot;0 0 24 24&quot; stroke-width=&quot;1.5&quot; stroke=&quot;currentColor&quot; class=&quot;w-5 h-5&quot;&gt;<br>                                              &lt;path stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot; d=&quot;M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0&quot; /&gt;<br>                                          &lt;/svg&gt;<br>                                      &lt;/button&gt;<br>                                  &lt;/form&gt;<br>                              &lt;/div&gt;<br>                          &lt;/td&gt;<br>                      &lt;/tr&gt;<br><br>                      @endforeach<br>                  &lt;/tbody&gt;<br>              &lt;/table&gt;<br>          &lt;/div&gt;<br>      &lt;/div&gt;<br>  &lt;/div&gt;<br>&lt;/div&gt;</pre><p>Now in order to make this work we can attach roles to the users using <strong>assignRole </strong>method :</p><pre>$user-&gt;assignRole(&#39;Seller&#39;);</pre><p>So lets say if you create a role and attach the permissions of creating the categories and viewing the categories .</p><p>Now in Spatie permissions package all the permissions will have gates assigned to them so you can do this to prevent users to access certain areas</p><p>Lets say if you want that only the role with the permissions of the <strong>categories create</strong> can only view the create category page/sections so you can do it like this :</p><p><strong>In Blade</strong></p><pre>@can(&#39;categories.create&#39;)<br>      &lt;div class=&quot;ml-auto px-3 py-1  text-blue-600 bg-blue-100 rounded-md&quot;&gt;<br>          &lt;a href=&quot;{{route(&#39;categories.create&#39;)}}&quot;&gt;Category Create&lt;/a&gt;<br>      &lt;/div&gt;<br>@endcan<br><br>//=============== OR FOR CHECKING MULTIPLE ABILITIES/PERMISSIONS ========== //<br><br>@canany([&#39;categories.create&#39;, &#39;categories.delete&#39;])<br>    &lt;div class=&quot;actions&quot;&gt;<br>        @can(&#39;categories.edit&#39;)<br>            &lt;button&gt;Edit&lt;/button&gt;<br>        @endcan<br>        @can(&#39;categories.delete&#39;)<br>            &lt;button&gt;Delete&lt;/button&gt;<br>        @endcan<br>    &lt;/div&gt;<br>@endcanany</pre><p><strong>In Controller:</strong></p><pre>public function createCategory()<br>{<br>    $this-&gt;authorize(&#39;categories.create&#39;);<br><br>    ================= OR =================<br><br>    if (Gate::allows(&#39;categories.create&#39;)) {<br>        // User is authorized, perform the action<br>    } else {<br>        abort(403); // Or redirect, or return an error response, depending on your needs<br>    }<br><br>    return view(&#39;admin.categories.create&#39;);<br>} </pre><p><strong>When Using the Middleware:</strong></p><pre>Route::group([&#39;middleware&#39; =&gt; [&#39;can:categories.create&#39;]], function () {<br>    //<br>});</pre><p>While storing/updating the data with Form Request Class:</p><p><strong>Requests/StoreCategories.php</strong></p><pre> public function authorize(): bool<br> {<br>    switch ($this-&gt;method()) {<br>        case &#39;POST&#39;:<br>            return $this-&gt;user()-&gt;can(&#39;categories.create&#39;);<br><br>            break;<br><br>        case &#39;PUT&#39;:<br>            return $this-&gt;user()-&gt;can(&#39;categories.edit&#39;);<br><br>            break;<br>    }<br><br>    return true;<br>}</pre><p><strong>Defining Super Admin:</strong></p><p>If you want a “Super Admin” role to respond true to all permissions, without needing to assign all those permissions to a role, you can use Laravel&#39;s Gate::before() method. For example:</p><pre>use Illuminate\Support\Facades\Gate;<br><br>class AuthServiceProvider extends ServiceProvider<br>{<br>    public function boot()<br>    {<br>        $this-&gt;registerPolicies();<br>        // Implicitly grant &quot;Super Admin&quot; role all permissions<br>        // This works in the app by using gate-related functions like auth()-&gt;user-&gt;can() and @can()<br>        Gate::before(function ($user, $ability) {<br>            return $user-&gt;hasRole(&#39;Super Admin&#39;) ? true : null;<br>        });<br>    }<br>}</pre><p>NOTE: Gate::before rules need to return null rather than false, else it will interfere with normal policy operation</p><p><strong>Best Practices from Spatie Permissions Package :</strong></p><p><strong>Roles</strong> are best to only assign to <strong>Users</strong> in order to “<strong>group</strong>” people by “<strong>sets of permissions</strong>”.</p><p><strong>Permissions</strong> are best assigned <strong>to roles</strong>. The more granular/detailed your permission-names (such as separate permissions like “view document” and “edit document”), the easier it is to control access in your application.</p><p><strong>Users</strong> should <em>rarely</em> be given “direct” permissions. Best if Users inherit permissions via the Roles that they’re assigned to.</p><p>When designed this way, all the sections of your application can check for specific permissions needed to access certain features or perform certain actions AND this way you can always <strong>use the native Laravel </strong><strong>@can and </strong><strong>can() directives everywhere</strong> in your app, which allows Laravel&#39;s Gate layer to do all the heavy lifting.</p><blockquote>I hope you thoroughly enjoyed reading this article.</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f20fe02a8c75" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How To Use Method Chaining And Using It To Simplify Your Laravel Code]]></title>
            <link>https://medium.com/@codeaxion77/how-to-use-method-chaining-and-using-it-to-simplify-your-laravel-code-a25212b18a0?source=rss-c43ba02a17a3------2</link>
            <guid isPermaLink="false">https://medium.com/p/a25212b18a0</guid>
            <category><![CDATA[php]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[object-oriented]]></category>
            <category><![CDATA[oop]]></category>
            <category><![CDATA[laravel]]></category>
            <dc:creator><![CDATA[Code Axion The Security Breach]]></dc:creator>
            <pubDate>Sun, 05 Mar 2023 11:08:23 GMT</pubDate>
            <atom:updated>2023-03-05T11:08:23.035Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QLSpTI79mg46QrF6ygJzYw.png" /></figure><blockquote>What is Method Chaining ?</blockquote><p>Method chaining is a powerful technique in object-oriented programming that allows you to call multiple methods on the same object in a single line of code. It’s a great way to streamline your code and make it more readable and maintainable so instead of this :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zAA4RQlyes5EEXE679DZoA.png" /></figure><p>we can do this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_JLnpjnxPjU7jPsdFDVghQ.png" /></figure><p>See its looks much more Cleaner and Readable .</p><p>So how can we achieve this ?</p><p>To implement method chaining, each method must return the object instance using the $this keyword at the end of the method like this :</p><pre>class MyClass {<br><br>  private $property1;<br>  private $property2;<br><br>  public function sum1($value) {<br>    $this-&gt;property1 = $value;<br>    return $this; &lt;---- returns the object instance <br>  }<br><br>  public function sum2($value) {<br>    $this-&gt;property2 = $value;<br>    return $this; &lt;---- returns the object instance<br>  }<br><br>  public function getResult() {<br>    $result = $this-&gt;property1 + $this-&gt;property2;<br>    return $result;<br>  }<br>}<br><br><br>$result = (new MyClass)-&gt;sum1(10)-&gt;sum2(20)-&gt;getResult();<br><br>dd($result);<br><br>//result: 30</pre><p>The last line of code creates a new instance of the MyClass class using the parentheses and then immediately calls the sum1() method with the argument 10. This returns the object instance, which is then used to call the sum2() method with the argument 20. This also returns the object instance, which is then used to call the getResult() method. The value of $property1 is 10 and the value of $property2 is 20, so the getResult() method returns 30.</p><p>Well How can we use this in real life case ?</p><p>Suppose you have 4 tasks to do :</p><blockquote>1. Create User</blockquote><blockquote>2. Attach Roles</blockquote><blockquote>3. Create User Company</blockquote><blockquote>4. Finally, get the user</blockquote><p>Now let’s do this with method chaining .</p><p>Let’s create a user Service class called ‘ <strong>UserService</strong>’ in <em>App\Services</em> folder .</p><p>Here we will define some methods which will be :<br>createUser(), handleRole(), createCompany(), getUser().</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FDqv56DFiWcHD1j-LUddbw.png" /></figure><p>As you can see on the first method we are creating the user by passing the request object in the parameter and after that we assign the newly created user to the user property by using :</p><pre>$this-&gt;user = $user &lt;--- assign the newly created user to user property  </pre><p>and then we return the object itself which helps us to allow method chaining further.</p><p>Now as the user property has now our user object , we can attach the roles of that user in handleRole method and return the instance .</p><pre>$this-&gt;user-&gt;roles()-&gt;attach([2,5]) &lt;--- we can even attach eloquent methods </pre><p>You can see more about chaining methods examples on this article:</p><blockquote><a href="https://medium.com/@codeaxion77/tired-of-writing-image-upload-code-create-this-reusable-service-in-laravel-c53489d44e55">Article: <strong>Tired of Writing Image Upload Code ? Create this Reusable Service In Laravel .</strong></a></blockquote><p>Now in createCompany method , as our user object is still present in user property we can create the company by passing the request object in createCompany method and pass the user_id foreign key from the user property if you want you can even pass the request object in the constructor method . After creating the company we will return $this which will allow for method chaining again .</p><p>After creating the company we have the getUser() method which will get our currently created user .</p><p>To try this service we can chain these methods in our controller like this :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YhuZb1kAXVEIXMJzNcqDBg.png" /></figure><p>Now in $user variable we will have the newly created user.</p><p>Hopefully, you have gained a better understanding of how method chaining is applied in real-life situations.</p><p><strong><em>If you liked this article, let me know what topic I should cover in the next one …</em></strong></p><p>Happy Coding : )</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a25212b18a0" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Tired of Writing Image Upload Code ? Create this Reusable Service In Laravel .]]></title>
            <link>https://medium.com/@codeaxion77/tired-of-writing-image-upload-code-create-this-reusable-service-in-laravel-c53489d44e55?source=rss-c43ba02a17a3------2</link>
            <guid isPermaLink="false">https://medium.com/p/c53489d44e55</guid>
            <category><![CDATA[code-refactoring]]></category>
            <category><![CDATA[laravel-framework]]></category>
            <category><![CDATA[php]]></category>
            <category><![CDATA[laravel]]></category>
            <category><![CDATA[oop]]></category>
            <dc:creator><![CDATA[Code Axion The Security Breach]]></dc:creator>
            <pubDate>Sun, 12 Feb 2023 14:33:58 GMT</pubDate>
            <atom:updated>2023-02-12T14:33:58.274Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*2LjkHIwu9YQDa-W-jS8EPQ.png" /></figure><p>Do you write image upload code ? if yes what do you do if you want to use the that code for 2 to 3 different models you make different service classes to do it right ? But, what if I told you that instead of creating multiple services, you could create just one service that can be used across all multiple sections ? , wouldn’t it be cool ?</p><p>Lets start by creating a service called <strong><em>ImageUploadService.php</em></strong> in the <strong>Services </strong>folder .</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/346/1*9dVpKwvj3vkGbrfXpNLarQ.png" /></figure><p>Now lets define a <strong>constructor </strong>in this class which will accept 3 parameters .</p><blockquote><strong>1st. Object type declaration as a parameter which will be the object of the model which we are gonna use for the image upload .</strong></blockquote><blockquote><strong>2nd. The actual image file which we we will get from the form .</strong></blockquote><blockquote><strong>3rd. The path where we will store the image in the public folder .</strong></blockquote><pre>&lt;?php<br><br>namespace App\Services;<br><br>class ImageUploadService{<br><br>  public $image;<br>  public $path;<br>  public $obj;<br>  <br>  function __construct(object $obj,$image = null,$path = null) //accepts object as a parameter<br>  {    <br>      $this-&gt;obj = $obj; &lt;-------- Your Model Object eg:- Product<br>      $this-&gt;image = $image; &lt;---- Your image file from the form   <br>      $this-&gt;path = $path; &lt;------ Your path where you want to store that file<br>  }<br><br>}</pre><blockquote>Now first lets define <strong>imageUpload() </strong>method.</blockquote><p>First we will check if the image exists and is not null and after that we will store the image to the folder by using the <strong>store()</strong> method and specifying the path in the parameter of where we want to put that image, the path will be the same which we defined in the constructor and finally we will return the object it self.</p><pre>&lt;?php<br><br>namespace App\Services;<br><br>class ImageUploadService{<br><br>  public $image;<br>  public $path;<br>  public $obj;<br>  <br>  function __construct(object $obj,$image,$path) //accepts object as a parameter<br>  {    <br>      $this-&gt;obj = $obj; &lt;-------- Your Model Object eg:- Product<br>      $this-&gt;image = $image; &lt;---- Your image file from the form   <br>      $this-&gt;path = $path; &lt;------ Your path where you want to store that file<br>  }<br><br><br>  public function uploadImage()<br>  {<br><br>      if($this-&gt;image &amp;&amp; $this-&gt;image !== null){<br><br>          //you can use store method to store the image to the folder<br>          //by specifying the image path .<br><br>          $this-&gt;image-&gt;store(&#39;public/&#39;. $this-&gt;path . &#39;/&#39;); <br>          <br>          return $this;<br>      }           <br><br>      return $this;<br>  }<br><br><br>}</pre><p>This section is storing the image to the folder now we have to save that image to the database.</p><blockquote>Lets define 2nd method which is <strong>storeImageDB()</strong> .</blockquote><p>Now <strong>storeImageDB()</strong> method will accept <em>1 parameter</em> which will be the column name of where you want to store the image path.</p><p>so the fieldName would be dynamic it could be anything like avatar, profile, logo etc…</p><p>We cannot hard code the property like this : $this-&gt;obj-&gt;avatar</p><p>so in order to make this property dynamic we could using curly braces around the object property like this :</p><pre>$dynamicProperty = &#39;avatar&#39;; <br><br>$this-&gt;obj-&gt;{$dynamicProperty} &lt;------ results as : $this-&gt;obj-&gt;avatar</pre><p>The next step is to define which object property we will use to store the image, which is : $this-&gt;obj-&gt;avatar</p><p>and the value would be the <em>path + the image name</em> added with md5 hash and we will return the object .</p><p>and later on we will execute this line on the controller which will save the image to the DB .</p><pre>public function storeImageDB($fieldName)<br>{<br><br>  if($fieldName &amp;&amp; $this-&gt;image){<br>                            <br>    $this-&gt;obj-&gt;{$fieldName} = $this-&gt;path . &#39;/&#39; . $this-&gt;image-&gt;hashName();<br><br>    //result: $this-&gt;obj-&gt;avatar = &#39;/product_images/0Dq4n3h0frEhi8AQCJULdtz.png/&#39;<br>    <br>    return $this-&gt;obj;<br>  }<br><br>  return $this;<br>}</pre><blockquote>Now lets write code for deleting the image .</blockquote><p>Lets define <strong><em>deleteImage() </em></strong>method:</p><p>This method will also accept one parameter, which is of course the field name, since we are checking if the object property product-&gt;avatar image exists in both the database and the folder . If it is we will delete the image by using the <strong>unlink() </strong>method .</p><pre>public function deleteImage($fieldName)<br>{<br>    $storePath = public_path(&#39;storage/&#39;. $this-&gt;obj-&gt;{$fieldName}); <br><br>    if($this-&gt;obj-&gt;{$fieldName} &amp;&amp; file_exists($storePath)){<br><br>        //unlink method will delete the image from the folder<br>        unlink(public_path(&#39;storage/&#39;.$this-&gt;obj-&gt;{$fieldName}));<br>    <br>        return $this;<br>    }<br><br>    return $this;<br>    <br>}</pre><p>So now our <strong>Service </strong>is ready to use !</p><p>but you will be like, ‘well hey ! you only showed us how to upload the image and delete the image , where is the update image part ? ’</p><p>You don’t need the update image method . confused ?</p><p>Well if you see for uploading the image we go in a pattern like this:</p><blockquote><strong>uploadImage -&gt; storeImage to Database</strong></blockquote><p>But if you wanna update the image and delete the previous image you can go like this:</p><blockquote><strong>deleteImage -&gt; uploadImage -&gt; storeImage to Database</strong></blockquote><p>So let me show how to use this method in the controller .</p><blockquote><strong>For Uploading The Image:</strong></blockquote><pre>public function storeProduct(Request $request)<br>{<br>//Do Some Validation.<br>$validator = $request-&gt;validate([<br><br>  &quot;name&quot; =&gt; [&#39;required&#39;],<br>  &quot;server_image&quot; =&gt;[&#39;image&#39;,&#39;max:2048&#39;],<br>]);<br> <br>//Create the product <br>---&gt; Model instance $product = Product::create([<br>    &quot;name&quot; =&gt; $request-&gt;name,<br>]);<br><br>  <br>$image = $request-&gt;file(&#39;server_image&#39;); &lt;--- the image file<br>$path = &#39;product_images&#39;; &lt;---- the path where we want to store the image to a folder<br><br>//Assign those values to constructor which is the model instance,the image and the path<br>$imageservice = new ImageUploadService($product,$image,$path);<br><br>//we will upload the image first and we will store that image to the database<br>$imageservice-&gt;uploadImage()-&gt;storeImageDB(&#39;server_image&#39;); //&lt;--- the field where you want to store the value in the table.<br><br>//Save the values to the database<br>$product-&gt;save();<br><br>}</pre><blockquote><strong>For Updating the Image:</strong></blockquote><pre>public function updateProduct(Request $request,$id)<br>{<br><br>$product = Product::findOrFail($id);<br><br>$product-&gt;name = $request-&gt;name;<br>   <br>//first we will check if the request has an image or not, if not we will not update the image<br>if (request()-&gt;hasFile(&#39;server_image&#39;) &amp;&amp; request(&#39;server_image&#39;) != &#39;&#39;) {<br>  <br>  //we will assign the model again, specify the file as the 2nd parameter<br>  //and the 3rd parameter as the path<br>  $imageservice = new ImageUploadService($product,$request-&gt;server_image,&#39;product_images&#39;);<br>          <br>  //now to update the image <br>  //first delete the image of the product<br>  //then upload the new image to the folder<br>  //and save that image to the database<br>  $imageservice-&gt;deleteImage(&#39;server_image&#39;)-&gt;uploadImage()-&gt;storeImageDB(&#39;server_image&#39;);<br>  <br>}<br><br>$product-&gt;update(); //update the product<br><br>}</pre><blockquote><strong>For Deleting the Image:</strong></blockquote><pre>public function deleteProduct($id)<br>{<br>  $product = Product::findOrFail($id);<br><br>  $imageservice = new ImageUploadService($product); //assign the model <br>  $imageservice-&gt;deleteImage(&#39;server_image&#39;); //and delete the image from the folder<br>}</pre><p><strong>I hope you find this article useful , do give it a share among communities and members .</strong></p><p><strong>Happy Coding !</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c53489d44e55" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Mastering Routes in Laravel: Best Practices .]]></title>
            <link>https://medium.com/@codeaxion77/mastering-routes-in-laravel-best-practices-2693f884aec9?source=rss-c43ba02a17a3------2</link>
            <guid isPermaLink="false">https://medium.com/p/2693f884aec9</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[laravel]]></category>
            <category><![CDATA[laravel-framework]]></category>
            <category><![CDATA[best-practices]]></category>
            <category><![CDATA[php]]></category>
            <dc:creator><![CDATA[Code Axion The Security Breach]]></dc:creator>
            <pubDate>Sat, 04 Feb 2023 15:12:58 GMT</pubDate>
            <atom:updated>2023-02-04T15:12:58.250Z</atom:updated>
            <content:encoded><![CDATA[<h3>Mastering Routes in Laravel: Best Practices .</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MTuKojB9BNid4Ldkh395-g.png" /></figure><p>Today i am gonna show you how to Organize Your Routes for the Large or Small Projects .</p><p><strong>1st. Organize routes to separate files .</strong></p><p>You might be having difficulty in organizing your routes in the web.php file, as all routes are clubbed into one single file and it can be a real hassle to find specific routes. For example, it may become challenging to differentiate between the admin routes, user routes, and role routes etc… , especially when you have a long list of routes in your web.php file and you may find yourself scrolling through numerous sections to find the specific route you’re looking for, which can be time-consuming and frustrating .</p><p>well i have an idea for you !</p><p>Suppose you have seller routes , buyer routes , admin routes ,user routes and some miscellaneous routes (notification, email) etc… now each of them contain more than 10 + routes , what you can do is create separate folders inside routes folder with the naming like this :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/358/1*rZ7qZO9ibrF2vO_654rUUQ.png" /></figure><p>now as you have separated your routes into folders then it should work right ? No !</p><p>In order to make this work you have to define those routes in boot method in <strong>RouteServiceProvider.php</strong> just like this</p><pre>public function boot()<br>{<br>    $this-&gt;configureRateLimiting();<br><br>    $this-&gt;routes(function () {<br>        Route::middleware(&#39;api&#39;)<br>            -&gt;prefix(&#39;api&#39;)<br>            -&gt;group(base_path(&#39;routes/api.php&#39;));<br><br>        Route::middleware(&#39;web&#39;)<br>            -&gt;namespace($this-&gt;namespace)<br>            -&gt;group(base_path(&#39;routes/web.php&#39;));<br><br>    //-------------- NEW ROUTES ---------------------//<br>        Route::middleware([&#39;web&#39;,&#39;auth&#39;,&#39;admin&#39;])<br>            -&gt;namespace($this-&gt;namespace)<br>            -&gt;group(base_path(&#39;routes/admin/admin.php&#39;));<br><br>        Route::middleware([&#39;web&#39;,&#39;auth&#39;,&#39;seller&#39;])<br>            -&gt;namespace($this-&gt;namespace)<br>            -&gt;group(base_path(&#39;routes/seller/seller.php&#39;));<br><br>        Route::middleware([&#39;web&#39;,&#39;auth&#39;,&#39;buyer&#39;])<br>            -&gt;namespace($this-&gt;namespace)<br>            -&gt;group(base_path(&#39;routes/buyer/buyer.php&#39;));<br><br>        Route::middleware([&#39;web&#39;,&#39;auth&#39;])<br>            -&gt;namespace($this-&gt;namespace)<br>            -&gt;group(base_path(&#39;routes/misc/misc.php&#39;));<br>    });<br>}</pre><p>Here in middleware method you can give the middleware name of what middleware you wanna use and in the<strong> group path</strong> you will define your route file path .</p><p>This is the one way actually or you could just simply include the file just like this:</p><pre>require __DIR__.&#39;/admin/admin.php&#39;;</pre><p>Well if you use the first idea you could get an idea how much Laravel framework is just capable of .</p><p><strong>2nd. Using Route Controller method and Middleware method</strong></p><p>Here you may see that are there several routes that are using the same controller and same Middlewares , this goes against <strong>DRY (Dont Repeat Yourself )Principle</strong>.</p><p><strong>Bad:</strong></p><pre>Route::get(&#39;/admin/categories/index&#39;, [CategoryController::class, &#39;index&#39;])-&gt;name(&#39;admin.category.index&#39;)-&gt;middleware([&#39;auth&#39;,&#39;admin&#39;]);<br>Route::get(&#39;/admin/categories/create&#39;, [CategoryController::class, &#39;create&#39;])-&gt;name(&#39;admin.category.create&#39;)-&gt;middleware([&#39;auth&#39;,&#39;admin&#39;]);<br>Route::POST(&#39;/admin/categories/index&#39;, [CategoryController::class, &#39;store&#39;])-&gt;name(&#39;admin.category.store&#39;)-&gt;middleware([&#39;auth&#39;,&#39;admin&#39;]);<br>Route::get(&#39;/admin/categories/edit/{category}&#39;, [CategoryController::class, &#39;edit&#39;])-&gt;name(&#39;admin.category.edit&#39;)-&gt;middleware([&#39;auth&#39;,&#39;admin&#39;]);<br>Route::PUT(&#39;/admin/categories/update/{category}&#39;,[CategoryController::class,&#39;update&#39;])-&gt;name(&#39;admin.category.update&#39;)-&gt;middleware([&#39;auth&#39;,&#39;admin&#39;]);<br>Route::DELETE(&#39;/admin/categories/delete/{category}&#39;, [CategoryController::class, &#39;delete&#39;])-&gt;name(&#39;admin.category.delete&#39;)-&gt;middleware([&#39;auth&#39;,&#39;admin&#39;]);</pre><p>so what we can do is we can group the routes with the group() method and assign a single Controller and multiple middlewares using the controller() and middleware() methods, respectively, like this:</p><p><strong>Good:</strong></p><pre>Route::controller(ProfileController::class)-&gt;middleware([&#39;auth&#39;,&#39;admin&#39;])-&gt;group(function() {<br><br>  Route::get(&#39;/admin/categories/index&#39;, &#39;index&#39;)-&gt;name(&#39;admin.category.index&#39;);<br>  Route::get(&#39;/admin/categories/create&#39;,&#39;create&#39;)-&gt;name(&#39;admin.category.create&#39;);<br>  Route::POST(&#39;/admin/categories/index&#39;,&#39;store&#39;)-&gt;name(&#39;admin.category.store&#39;);<br>  Route::get(&#39;/admin/categories/edit/{category}&#39;, &#39;edit&#39;)-&gt;name(&#39;admin.category.edit&#39;);<br>  Route::PUT(&#39;/admin/categories/update/{category}&#39;,&#39;update&#39;)-&gt;name(&#39;admin.category.update&#39;);<br>  Route::DELETE(&#39;/admin/categories/delete/{category}&#39;, &#39;delete&#39;)-&gt;name(&#39;admin.category.delete&#39;);<br>  <br>});</pre><p><strong>3rd. Group routes by names and prefixes .</strong></p><p>Now if you carefully see we are using the same url for the crud which is <strong>“/admin/products/”</strong> and the same thing is happening with the route names , we are defining <strong><em>admin.products</em></strong> and<strong><em> /admin/products</em></strong> again and again just like the above example so what we can do is we can use prefix and name method into the group like this:</p><pre> Route::controller(CategoryController::class)<br>  -&gt;middleware([&#39;auth&#39;,&#39;admin&#39;])<br>  -&gt;prefix(&#39;admin/categories&#39;)<br>  -&gt;namespace(&#39;Backend&#39;) //if you have one more folder inside Controllers you can specify namespaces too<br>  -&gt;name(&#39;admin.category.&#39;)-&gt;group(function() {<br><br>   Route::get(&#39;index&#39;, &#39;index&#39;)-&gt;name(&#39;index&#39;);<br>   Route::get(&#39;create&#39;,&#39;create&#39;)-&gt;name(&#39;create&#39;);<br>   Route::POST(&#39;index&#39;,&#39;store&#39;)-&gt;name(&#39;store&#39;);<br>   Route::get(&#39;edit/{product}&#39;, &#39;edit&#39;)-&gt;name(&#39;edit&#39;);<br>   Route::PUT(&#39;update/{category}&#39;,&#39;update&#39;)-&gt;name(&#39;update&#39;);<br>   Route::DELETE(&#39;delete/{category}&#39;, &#39;delete&#39;)-&gt;name(&#39;delete&#39;);<br><br>});</pre><p><strong>this is also equivalent to this:</strong></p><pre>Route::group([<br><br>    &#39;middleware&#39; =&gt; [&#39;admin&#39;,&#39;auth&#39;],<br>    //if you have one more folder inside Controllers you can specify namespaces too<br>    &#39;namespace&#39; =&gt; &#39;Backend&#39;, <br>    &#39;controller&#39; =&gt; CategoryController::class,<br>    &#39;prefix&#39; =&gt; &#39;admin/categories&#39;,<br>    &#39;as&#39; =&gt; &#39;admin.category.&#39;,<br><br>],function() {<br><br>    Route::get(&#39;index&#39;, &#39;index&#39;)-&gt;name(&#39;index&#39;);<br>    Route::get(&#39;create&#39;,&#39;create&#39;)-&gt;name(&#39;create&#39;);<br>    Route::POST(&#39;index&#39;,&#39;store&#39;)-&gt;name(&#39;store&#39;);<br>    Route::get(&#39;edit/{category}&#39;, &#39;edit&#39;)-&gt;name(&#39;edit&#39;);<br>    Route::PUT(&#39;update/{category}&#39;,&#39;update&#39;)-&gt;name(&#39;update&#39;);<br>    Route::DELETE(&#39;delete/{category}&#39;, &#39;delete&#39;)-&gt;name(&#39;delete&#39;);<br>});</pre><p>and is also equivalent to this too if you have separate file for routes (mentioned in first example) :</p><p><strong>RouteServiceProvider.php</strong></p><pre>protected $namespace = &#39;App\Http\Controllers&#39;;<br><br>Route::middleware([&#39;web&#39;,&#39;auth&#39;,&#39;admin&#39;]) //&lt;------ your Middlewares array<br>    -&gt;namespace($this-&gt;namespace . &#39;\Backend&#39;) //&lt;------ your Custom Namespace <br>    -&gt;prefix(&#39;admin/categories&#39;) //&lt;-------- URL prefixes<br>    -&gt;name(&#39;admin.category.&#39;) //&lt;----------- your routes names <br>    -&gt;group(base_path(&#39;routes/admin.php&#39;)); //&lt;-------- your routes file path</pre><p><strong>/routes/admin/admin.php</strong></p><pre><br>use Illuminate\Support\Facades\Route;<br><br>Route::controller(CategoryController::class)-&gt;group(function() {<br><br>    Route::get(&#39;index&#39;, &#39;index&#39;)-&gt;name(&#39;index&#39;);<br>    Route::get(&#39;create&#39;,&#39;create&#39;)-&gt;name(&#39;create&#39;);<br>    Route::POST(&#39;index&#39;,&#39;store&#39;)-&gt;name(&#39;store&#39;);<br>    Route::get(&#39;edit/{category}&#39;, &#39;edit&#39;)-&gt;name(&#39;edit&#39;);<br>    Route::PUT(&#39;update/{category}&#39;,&#39;update&#39;)-&gt;name(&#39;update&#39;);<br>    Route::DELETE(&#39;delete/{category}&#39;, &#39;delete&#39;)-&gt;name(&#39;delete&#39;);<br><br>});</pre><p>You can see our routes looks much more sleeker now .</p><p>so if you want to organize your routes for Large/Small projects this is the best way .</p><p>Here are some key points of what we learned today :</p><blockquote><strong>1st.</strong> Organize Your Routes to separate folders</blockquote><blockquote><strong>2nd.</strong> Use <strong>Middleware() </strong>and <strong>controller()</strong> method to share single controller and multiple middlewares to all the routes .</blockquote><blockquote><strong>3rd: </strong>Use <strong>prefix()</strong> and <strong>name()</strong> method to share common url prefixes and route names to all the routes .</blockquote><p>If you have read this far , I Really Appreciate Your Time . Thank you !</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2693f884aec9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How To Switch Roles From Seller To Buyer like Fiverr in Laravel]]></title>
            <link>https://medium.com/@codeaxion77/how-to-switch-roles-from-seller-to-buyer-like-fiverr-in-laravel-2294df9088?source=rss-c43ba02a17a3------2</link>
            <guid isPermaLink="false">https://medium.com/p/2294df9088</guid>
            <category><![CDATA[laravel]]></category>
            <category><![CDATA[php]]></category>
            <category><![CDATA[authorization]]></category>
            <category><![CDATA[laravel-framework]]></category>
            <dc:creator><![CDATA[Code Axion The Security Breach]]></dc:creator>
            <pubDate>Sat, 14 Jan 2023 19:36:40 GMT</pubDate>
            <atom:updated>2023-01-14T19:36:40.989Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*57JVA1cFolr_vGX7M_0a-g.png" /></figure><p>As you have seen in my<strong><em> </em></strong><a href="https://medium.com/@codeaxion77/build-different-panels-for-different-users-in-laravel-using-gates-part-1-981fada44554"><strong><em>previous Story</em></strong>,</a> i have explained how to create dashboard for different roles, so in today’s article i am gonna show you how you can switch roles from seller to buyer or buyer to seller like <strong>Fiverr</strong>.</p><p>In order to make the switching dashboard work , we have to know what role is currently active of the <strong>Auth </strong>user for Eg:- if the user is logged in as a role <strong>seller </strong>his active role would be 2 and if the user is logged in as a <strong>buyer </strong>his active role should be 1 because here we will not be displaying contents according to the <strong>Auth </strong>user , we will be displaying contents according to the role .</p><p><strong>Our Main Recipe of making this Feature is 2 things (Important):</strong></p><p><strong>1st :</strong> We will define an active_role field in the user’s table and we can check if the user active_role field is 2 that means he is seller else if its 1 he is a buyer .</p><p><strong>2nd: </strong>So as we have defined buyer and seller gates in the previous story , we write a logic in such a way that , if the user active_role is 2 (seller ) he can access the seller gate and if its 1 (buyer) he can access the buyer gate .</p><p>That is the 2 main logic of entire feature now in order make this work we have to update the active role field by the click of a button, if he clicks on switch to seller his active role have to be updated from 1 to 2 .</p><p>Lets create a column called <strong><em>active_role </em></strong>on the users table , and lets add 1 by default which is the <strong>Buyer </strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DyEWWU_wJo1XXyJqcZySWw.png" /></figure><p>As according to our <strong>2nd Recipe</strong> we have to access the seller and buyer gates according to the active_roles, now lets customize the gates that we made in the previous story .</p><p><strong>Seller Gate:</strong></p><p>We will first verify if the user has more than 0 roles. Next, we will determine if the user has an active role. If they do, we will check if the active role is 2 (seller) and If the user has more than one role, we will search for a role with an ID that matches the user’s active role field and return it. If we find one, we will return true. Otherwise, we will return the seller role.</p><p>This will let us access the seller gate if the active role is 2 .</p><pre>Gate::define(&#39;Seller-only&#39;,function($user)<br>{<br>    <br>  if(count($user-&gt;roles) &gt; 0){<br>     <br>      if($user-&gt;active_role){<br>          <br>          if($user-&gt;active_role == 2 &amp;&amp; $user-&gt;roles-&gt;count() == 2){<br><br>              return ($user-&gt;roles()-&gt;where(&#39;role_id&#39;,$user-&gt;active_role)-&gt;first()-&gt;name == &#39;Seller&#39;);<br>          }<br>      <br>      }<br><br>      return ($user-&gt;roles-&gt;first()-&gt;name === &#39;Seller&#39; );<br>  }<br><br>});</pre><p><strong>2. Buyer Gate:</strong></p><p>We will do the same thing for the Buyer now .</p><pre>Gate::define(&#39;Buyer-Only&#39;,function($user)<br>    {<br>      if(count($user-&gt;roles) &gt; 0){<br>            <br>          <br>        if($user-&gt;active_role){<br>          <br>            if($user-&gt;active_role == 1 &amp;&amp; $user-&gt;roles-&gt;count() == 2){<br><br>                return ($user-&gt;roles()-&gt;where(&#39;role_id&#39;,$user-&gt;active_role)-&gt;first()-&gt;name == &#39;Buyer&#39;);<br>            }<br>        <br>        }<br>        <br>          return ($user-&gt;roles-&gt;first()-&gt;name === &#39;Buyer&#39;);<br>      }<br><br>    });</pre><p><strong>3rd Seller-Admin-Buyer (To access the same page for all the roles as discussed in the previous story ) :</strong></p><pre> Gate::define(&#39;Seller-Admin-Buyer&#39;,function($user)<br>  {<br><br>      if(count($user-&gt;roles) &gt; 0){<br>       <br>          $userRole = $user-&gt;roles-&gt;first()-&gt;name;<br><br>          if($user-&gt;active_role){<br><br>              <br>              if($user-&gt;active_role == 2 &amp;&amp; $user-&gt;roles-&gt;count() == 2){<br><br>             <br>                  return ($user-&gt;roles()-&gt;where(&#39;role_id&#39;,$user-&gt;active_role)-&gt;first()-&gt;name == &#39;Seller&#39;);<br>              }<br><br>              if($user-&gt;active_role == 1 &amp;&amp; $user-&gt;roles-&gt;count() == 2){<br><br>                  <br>                  return ($user-&gt;roles()-&gt;where(&#39;role_id&#39;,$user-&gt;active_role)-&gt;first()-&gt;name == &#39;Buyer&#39;);<br>              }<br><br>          }<br>          <br>          return ($user-&gt;roles-&gt;first()-&gt;name === &#39;Seller&#39; ) || ($user-&gt;roles-&gt;first()-&gt;name === &#39;Buyer&#39; );<br><br>      }<br>      <br>      return ($user-&gt;is_admin === 777);<br>  });</pre><p>Lets create a form , routes and function so that we can update active_role on a click of a button “S<strong>witch to Seller / Buyer</strong> ”</p><p><strong>In Routes file :</strong></p><pre>Route::put(&#39;/change/role&#39;,[DashboardController::class,&#39;changeRole&#39;])-&gt;name(&#39;change-role&#39;);</pre><p><strong>In Navbar.blade.php View (form section):</strong></p><p>So by clicking on the <strong>Switching button, </strong>active_role field of the user will be updated .</p><p>If the active_role of the user is 2 and if he wants to <em>switch to buyer</em>, we will send the <em>active_role</em> request as 1 in the controller and if he wants to “<em>switch to seller”</em> we will send the request as 2 which is seller and we will differentiate the values using gates like below .</p><pre>&lt;form action=&quot;{{route(&#39;change-role&#39;)}}&quot; method=&quot;POST&quot;&gt;<br>  @csrf<br>  @method(&#39;PUT&#39;)<br><br>  @can(&#39;Seller-only&#39;)<br>  &lt;input type=&quot;hidden&quot; value=&quot;1&quot; name=&quot;role_type&quot;&gt;<br>  &lt;button type=&quot;submit&quot; class=&quot;bg-emerald-200 w-full text-emerald-700 px-2 py-1 rounded font-medium&quot;&gt;Switch to Buyer&lt;/button&gt;<br>  <br><br>  @elsecan(&#39;Buyer-Only&#39;)<br>  &lt;input type=&quot;hidden&quot; value=&quot;2&quot; name=&quot;role_type&quot;&gt;<br>  &lt;button type=&quot;submit&quot; class=&quot;bg-blue-200 w-full text-blue-700 px-2 py-1 rounded font-medium&quot;&gt;Switch to Seller&lt;/button&gt;<br><br>  @endcan<br>&lt;/form&gt;<br><br><br><br>//TO CHECK IF THE USER IS LOGGED IN AS A BUYER OR AS A SELLER (IMPORTANT)<br><br>  &lt;h1 class=&quot;font-semibold mx-2&quot;&gt; Logged In As,&lt;/h1&gt; {{Auth::user()-&gt;name}}<br>                <br>   @if (Auth::user()-&gt;active_role)<br>           <br>      @if (Auth::user()-&gt;active_role == 2)<br>      <br>      &lt;h1 class=&quot;text-xs bg-blue-600  rounded px-1 py-0.5 w-fit text-blue-100&quot;&gt;Seller&lt;/h1&gt;<br>      @elseif(Auth::user()-&gt;active_role == 1)<br>      <br>          &lt;h1 class=&quot;text-xs bg-emerald-600  rounded px-1 py-0.5 w-fit text-emerald-100&quot;&gt; Buyer &lt;/h1&gt;<br>    @endif<br><br>    @else<br>  <br>      @if (Auth::user()-&gt;roles-&gt;first() &amp;&amp; Auth::user()-&gt;roles-&gt;first()-&gt;name == &#39;Seller&#39;)<br>      <br>      &lt;h1 class=&quot;text-xs bg-blue-600  rounded px-1 py-0.5 w-fit text-blue-100&quot;&gt;{{Auth::user()-&gt;roles-&gt;first()-&gt;name}} &lt;/h1&gt;<br><br>      @elseif(Auth::user()-&gt;roles-&gt;first() &amp;&amp; Auth::user()-&gt;roles-&gt;first()-&gt;name == &#39;Buyer&#39;)<br>      &lt;h1 class=&quot;text-xs bg-emerald-600  rounded px-1 py-0.5 w-fit text-emerald-100&quot;&gt;{{ Auth::user()-&gt;roles-&gt;first()-&gt;name}} &lt;/h1&gt;<br><br>          @endif<br><br>  @endif</pre><p><strong>In Dashboard Controller:</strong></p><pre> public function changeRole(Request $request)<br>  {<br>      <br>      if($request-&gt;role_type == 1){<br>          <br>          $user = User::findOrFail(Auth::id());<br>          $user-&gt;active_role = 1;<br>          $user-&gt;save();<br><br>          return redirect()-&gt;route(&#39;admin-dashboard&#39;)-&gt;with(&#39;switch_role&#39;,&#39;Switched To Buyer&#39;);<br>      };<br><br>      $user = User::findOrFail(Auth::id());<br>      $user-&gt;active_role = 2;<br>      $user-&gt;save();<br><br>      return redirect()-&gt;route(&#39;admin-dashboard&#39;)-&gt;with(&#39;switch_role&#39;,&#39;Switched To Seller&#39;);<br><br>  }</pre><p><strong>Now lets preview this :</strong></p><p>Currently i am logged in as a seller and i want to switch to buyer so my current gate which is active is ‘<strong>Seller-Only’</strong> which means as the form mentioned above my request role_id will be sent to the controller will be 1 .</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VHl_28cdmSvBOgFyhhE8vQ.png" /></figure><p>Now as i click on the switch to buyer my <strong>active_role </strong>field on the table will be updated to 1 (Buyer) and i will be able to access the<strong> Buyer gate</strong> .</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j6HQV4aTUMzM4Gzk7aTuug.png" /></figure><p>I hope you enjoyed my article feel free to comment and leave suggestions or ideas …</p><p><strong><em>Happy Coding !</em></strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2294df9088" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How To Build Different Dashboards For Different Roles In Laravel Using Gates Part 1]]></title>
            <link>https://medium.com/@codeaxion77/build-different-panels-for-different-users-in-laravel-using-gates-part-1-981fada44554?source=rss-c43ba02a17a3------2</link>
            <guid isPermaLink="false">https://medium.com/p/981fada44554</guid>
            <category><![CDATA[laravel-development]]></category>
            <category><![CDATA[authorization]]></category>
            <category><![CDATA[laravel-framework]]></category>
            <category><![CDATA[laravel]]></category>
            <dc:creator><![CDATA[Code Axion The Security Breach]]></dc:creator>
            <pubDate>Sun, 01 Jan 2023 18:10:42 GMT</pubDate>
            <atom:updated>2023-01-01T18:14:01.382Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JuJf2dmu3hriE5IPiSKm6A.png" /></figure><p>Today we are gonna see how we can create different dashboards for different permissions of multiple users.</p><blockquote>I won’t show you how to create relationships or do the migrations and installing the projects and stuffs … i will assume you have some intermediate knowledge of laravel , Relationships etc...</blockquote><p><strong>Pre-requisite: Intermediate Knowledge Of Laravel, Strong Knowledge Of DB Design &amp; Management, Authorization and Authentication skills .</strong></p><p>First of all we will install the <strong>Laravel Breeze Package</strong> and we will migrate all the default tables for the project setup.</p><p>Now the main concept is, a user can be a seller, buyer or both and there will be 1 admin , so each role can have mulitple users for eg:- a user can be a buyer and a seller too, so in this case we are going to use many to many relationships .</p><blockquote><strong>IMPORTANT: In Part 1 , we will only build Seller, Buyer and Admin Dashboard, the both role section will be in part 2 of the article where user can switch roles between buyer and seller ( both )</strong></blockquote><pre>Schema::create(&#39;users&#39;, function (Blueprint $table) {<br>$table-&gt;increments(&#39;id&#39;);<br>    $table-&gt;string(&#39;name&#39;);<br>    $table-&gt;string(&#39;email&#39;)-&gt;unique();<br>    $table-&gt;timestamps();<br>});</pre><p><strong>Create Migration of Roles Table</strong></p><pre>Schema::create(&#39;roles&#39;, function (Blueprint $table) {<br>$table-&gt;increments(&#39;id&#39;);<br>    $table-&gt;string(&#39;name&#39;);<br>    $table-&gt;timestamps();<br>});</pre><p>Lets create a pivot table called user_role and add the user_id and role_id in the pivot table .</p><pre>Schema::create(&#39;role_users&#39;, function (Blueprint $table) {<br>$table-&gt;integer(&#39;user_id&#39;)-&gt;unsigned();<br>    $table-&gt;integer(&#39;role_id&#39;)-&gt;unsigned();<br>    $table-&gt;foreign(&#39;user_id&#39;)-&gt;references(&#39;id&#39;)-&gt;on(&#39;users&#39;)-&gt;onDelete(&#39;cascade&#39;);<br>    $table-&gt;foreign(&#39;role_id&#39;)-&gt;references(&#39;id&#39;)-&gt;on(&#39;roles&#39;)-&gt;onDelete(&#39;cascade&#39;);<br>});</pre><p>now attach the relationships in the User &amp; Role model like this:</p><pre>&lt;?php<br>namespace App\Models;<br>use Illuminate\Database\Eloquent\Model;<br>class User extends Model<br>{<br>  <br>    public function roles()<br>    {<br>        return $this-&gt;belongsToMany(Role::class, &#39;role_users&#39;);<br>    }<br>}</pre><p><strong>Role Model:</strong></p><pre>&lt;?php<br>namespace App\Models;<br>use Illuminate\Database\Eloquent\Model;<br>class Role extends Model<br>{    <br>    public function user()<br>    {<br>        return $this-&gt;belongsToMany(User::class, &#39;role_users&#39;);<br>    }<br>}</pre><p>Now lets define some gates in<em> A</em><strong><em>uth Service Provider</em> </strong>of A<em>dmin </em>, S<em>eller </em>, B<em>uyer</em>.</p><p>First we will create a Admin Gate where we will authorize if the user is admin or not we will pass the user as the parameter and we will check if the user-&gt;is_admin === 777 , now gates returns the results in true or false , so if the gate value is true , it will allow us to access the admin section .</p><pre>Gate::define(&#39;SuperAdmin-only&#39;,function($user)<br>{<br>  return ($user-&gt;is_admin === 777); <br><br>});</pre><p>Now lets create a seller and buyer gates, first we will check if the user has any roles , if yes we will check if he is a buyer or seller and return true or false according to the conditions like this:</p><pre>Gate::define(&#39;Seller-only&#39;,function($user)<br>{<br>  <br>  if(count($user-&gt;roles) &gt; 0){<br>     <br>      return ($user-&gt;roles-&gt;first()-&gt;name === &#39;Seller&#39; );<br>  }<br><br>});<br><br><br>Gate::define(&#39;Buyer-only&#39;,function($user)<br>{<br>  <br>  if(count($user-&gt;roles) &gt; 0){<br>     <br>      return ($user-&gt;roles-&gt;first()-&gt;name === &#39;Buyer&#39; );<br>  }<br><br>});</pre><p>Now this is where the crazy part comes, now you wont create a page for every roles right ? that will be little messy !</p><p>So instead we will be creating only 1 page for every role and we will differentiate the sections using <strong>“@can” </strong>method in Laravel .</p><p>But how can we allow multiple users with different roles or permissions to access the same page for eg: dashboard, well you can use the or method in your gates to combine multiple conditions like this :</p><pre>Gate::define(&#39;Seller-only&#39;,function($user)<br>{<br>  <br>  if(count($user-&gt;roles) &gt; 0){<br>     <br>      return ($user-&gt;roles-&gt;first()-&gt;name === &#39;Seller&#39; ) || return ($user-&gt;roles-&gt;first()-&gt;name === &#39;Buyer );<br>  }<br><br>  return ($user-&gt;is_admin === 777);<br><br>});</pre><p>Now lets create route for dashboard, now if you noticed here we have added the gate <strong>Seller-Admin-Buyer</strong> middleware: this will allow mulitple users with different roles to access the same page . So seller, admin and buyer can access the same dashboard page and later on we can differentiate the dashboard sections with the <strong><em>can </em></strong>method later .</p><pre>Route::group([&#39;middleware&#39; =&gt; [&#39;auth&#39;,&#39;can:Seller-Admin-Buyer&#39;]], function (){<br><br>    Route::get(&#39;/dashboard&#39;,[DashboardController::class,&#39;dashboard&#39;])-&gt;name(&#39;dashboard&#39;);<br><br>});</pre><p>Now lets customize the view of the dashboard :</p><pre>dashboard.blade.php<br><br>@if (Auth::user()-&gt;roles-&gt;first())<br><br>  Welcome To {{Auth::user()-&gt;roles-&gt;first()-&gt;name}} Dashboard, {{Auth::user()-&gt;name}}<br><br>@endif<br><br>@if (Auth::user()-&gt;is_admin === 777)<br>   Welcome To ADMIN Dashboard, {{Auth::user()-&gt;name}}<br>@endif<br></pre><p>Now lets create 2 roles for <strong><em>seller </em></strong>and <strong><em>buyer </em></strong>on roles table like this :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/603/1*RPU588U2MPzWoLvsUgDbWg.png" /></figure><p>and also register 2 new users and attach the role id of 1 and 2 in the users_roles pivot table like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/689/1*MywKDa2Huwuvu4lpeRXwrw.png" /></figure><p>Now this is what welcome dashboard will look like for buyers :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*16EKPEAF3HMpU_GRnzWL0A.png" /></figure><p>Now lets login as 2nd user who is <strong><em>seller </em></strong>and attach a role id of 2 in the users_roles pivot table as we did in the previous part, his welcome dashboard will look this this :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Htef0vEBL_M23nWTHwj4Pw.png" /></figure><p>Now login as an admin whose <strong><em>is_admin </em></strong>value is <em>777 </em>on the users table , his dashboard will look like this :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oWkeyXuuVKRqZYOyHCrBow.png" /></figure><p>Now lets create sidebar links with <strong>“@can</strong>” method to separate links of each roles . seller will have features to manage orders , sell products, create coupons etc…</p><blockquote>The Can method starts with <strong>“@can + {<em>the gate name</em>} ”</strong></blockquote><p>Here we are using <strong><em>can method </em></strong>with S<strong><em>eller gate</em></strong>, which means only seller will have access to this particular section links !</p><pre>@can(&#39;Seller-only&#39;) //we will use can <br>   <br>  &lt;a class=&quot;flex items-center px-4 py-2 mt-5 text-gray-600 transition-colors duration-300 transform rounded-md dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-700 dark:hover:text-gray-200 hover:text-gray-700&quot; href=&quot;{{route(&#39;my-product&#39;)}}&quot;&gt;<br><br>       &lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;16&quot; height=&quot;16&quot; fill=&quot;currentColor&quot; class=&quot;w-5 h-5 bi bi-bag-check&quot; viewBox=&quot;0 0 16 16&quot;&gt;<br>         &lt;path fill-rule=&quot;evenodd&quot; d=&quot;M10.854 8.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708 0z&quot;/&gt;<br>          &lt;path d=&quot;M8 1a2.5 2.5 0 0 1 2.5 2.5V4h-5v-.5A2.5 2.5 0 0 1 8 1zm3.5 3v-.5a3.5 3.5 0 1 0-7 0V4H1v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-3.5zM2 5h12v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5z&quot;/&gt;<br>        &lt;/svg&gt;<br>      &lt;span class=&quot;mx-4 font-medium&quot;&gt;<br>          Sell Products<br>      &lt;/span&gt;<br>   &lt;/a&gt;<br><br>  &lt;a class=&quot;flex items-center px-4 py-2 mt-5 text-gray-600 transition-colors duration-300 transform rounded-md dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-700 dark:hover:text-gray-200 hover:text-gray-700&quot; href=&quot;{{route(&#39;my-product&#39;)}}&quot;&gt;<br><br>      &lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;16&quot; height=&quot;16&quot; fill=&quot;currentColor&quot; class=&quot;w-5 h-5 bi bi-bag-check&quot; viewBox=&quot;0 0 16 16&quot;&gt;<br>        &lt;path fill-rule=&quot;evenodd&quot; d=&quot;M10.854 8.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708 0z&quot;/&gt;<br>         &lt;path d=&quot;M8 1a2.5 2.5 0 0 1 2.5 2.5V4h-5v-.5A2.5 2.5 0 0 1 8 1zm3.5 3v-.5a3.5 3.5 0 1 0-7 0V4H1v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-3.5zM2 5h12v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5z&quot;/&gt;<br>       &lt;/svg&gt;<br>     &lt;span class=&quot;mx-4 font-medium&quot;&gt;<br>         Create Coupons<br>     &lt;/span&gt;<br>  &lt;/a&gt;<br><br>  &lt;a class=&quot;flex items-center px-4 py-2 mt-5 text-gray-600 transition-colors duration-300 transform rounded-md dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-700 dark:hover:text-gray-200 hover:text-gray-700&quot; href=&quot;{{route(&#39;my-product&#39;)}}&quot;&gt;<br><br>      &lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;16&quot; height=&quot;16&quot; fill=&quot;currentColor&quot; class=&quot;w-5 h-5 bi bi-bag-check&quot; viewBox=&quot;0 0 16 16&quot;&gt;<br>        &lt;path fill-rule=&quot;evenodd&quot; d=&quot;M10.854 8.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708 0z&quot;/&gt;<br>         &lt;path d=&quot;M8 1a2.5 2.5 0 0 1 2.5 2.5V4h-5v-.5A2.5 2.5 0 0 1 8 1zm3.5 3v-.5a3.5 3.5 0 1 0-7 0V4H1v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-3.5zM2 5h12v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5z&quot;/&gt;<br>       &lt;/svg&gt;<br>     &lt;span class=&quot;mx-4 font-medium&quot;&gt;<br>         Manage Orders<br>     &lt;/span&gt;<br>  &lt;/a&gt;<br>@endcan</pre><p>Now lets create links for <strong>buyers </strong>as well, we are giving permissions to buyers that they can buy the products, view their order history , track order etc…</p><pre>@can(&#39;Buyer-Only&#39;)<br>       <br>  &lt;a class=&quot;flex items-center px-4 py-2 mt-5 text-gray-600 transition-colors duration-300 transform rounded-md dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-700 dark:hover:text-gray-200 hover:text-gray-700&quot; href=&quot;{{route(&#39;my-product&#39;)}}&quot;&gt;<br><br>       &lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;16&quot; height=&quot;16&quot; fill=&quot;currentColor&quot; class=&quot;w-5 h-5 bi bi-bag-check&quot; viewBox=&quot;0 0 16 16&quot;&gt;<br>         &lt;path fill-rule=&quot;evenodd&quot; d=&quot;M10.854 8.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708 0z&quot;/&gt;<br>          &lt;path d=&quot;M8 1a2.5 2.5 0 0 1 2.5 2.5V4h-5v-.5A2.5 2.5 0 0 1 8 1zm3.5 3v-.5a3.5 3.5 0 1 0-7 0V4H1v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-3.5zM2 5h12v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5z&quot;/&gt;<br>        &lt;/svg&gt;<br>      &lt;span class=&quot;mx-4 font-medium&quot;&gt;<br>          Buy Products<br>      &lt;/span&gt;<br>   &lt;/a&gt;<br><br>  &lt;a class=&quot;flex items-center px-4 py-2 mt-5 text-gray-600 transition-colors duration-300 transform rounded-md dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-700 dark:hover:text-gray-200 hover:text-gray-700&quot; href=&quot;{{route(&#39;my-product&#39;)}}&quot;&gt;<br><br>      &lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;16&quot; height=&quot;16&quot; fill=&quot;currentColor&quot; class=&quot;w-5 h-5 bi bi-bag-check&quot; viewBox=&quot;0 0 16 16&quot;&gt;<br>        &lt;path fill-rule=&quot;evenodd&quot; d=&quot;M10.854 8.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708 0z&quot;/&gt;<br>         &lt;path d=&quot;M8 1a2.5 2.5 0 0 1 2.5 2.5V4h-5v-.5A2.5 2.5 0 0 1 8 1zm3.5 3v-.5a3.5 3.5 0 1 0-7 0V4H1v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-3.5zM2 5h12v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5z&quot;/&gt;<br>       &lt;/svg&gt;<br>     &lt;span class=&quot;mx-4 font-medium&quot;&gt;<br>         My Orders History<br>     &lt;/span&gt;<br>  &lt;/a&gt;<br><br>  &lt;a class=&quot;flex items-center px-4 py-2 mt-5 text-gray-600 transition-colors duration-300 transform rounded-md dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-700 dark:hover:text-gray-200 hover:text-gray-700&quot; href=&quot;{{route(&#39;my-product&#39;)}}&quot;&gt;<br><br>      &lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;16&quot; height=&quot;16&quot; fill=&quot;currentColor&quot; class=&quot;w-5 h-5 bi bi-bag-check&quot; viewBox=&quot;0 0 16 16&quot;&gt;<br>        &lt;path fill-rule=&quot;evenodd&quot; d=&quot;M10.854 8.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 0 1 .708-.708L7.5 10.793l2.646-2.647a.5.5 0 0 1 .708 0z&quot;/&gt;<br>         &lt;path d=&quot;M8 1a2.5 2.5 0 0 1 2.5 2.5V4h-5v-.5A2.5 2.5 0 0 1 8 1zm3.5 3v-.5a3.5 3.5 0 1 0-7 0V4H1v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V4h-3.5zM2 5h12v9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5z&quot;/&gt;<br>       &lt;/svg&gt;<br>     &lt;span class=&quot;mx-4 font-medium&quot;&gt;<br>         Track Order<br>     &lt;/span&gt;<br>  &lt;/a&gt;<br>@endcan</pre><p>This is what B<strong>uyer and Seller</strong> dashboard sidebar will look like finally:</p><p><strong>Seller Dashboard:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mHelfbANE5sZr4d8watn2w.png" /></figure><p><strong>Buyer Dashboard:</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zCM-z7x_x2ZbwJdVSfJOSw.png" /></figure><p>Now just like that you can create routes for sellers and buyer like this and differentiate them with “<strong><em>can ” </em></strong>and “<strong><em>cannot ” </em></strong>methods in Laravel and add it to your customization&#39;s and your personal preferences .</p><pre>Route::group([&#39;middleware&#39; =&gt; [&#39;auth&#39;,&#39;can:Seller-only&#39;]], function (){<br><br>   Route::get(&#39;/seller/manage-orders&#39;, [OrderController::class, &#39;manageOrders&#39;])-&gt;name(&#39;manage.orders&#39;);<br>   <br>   ...more seller routes<br><br>   // only sellers can access this pages<br>});</pre><pre><br>Route::group([&#39;middleware&#39; =&gt; [&#39;auth&#39;,&#39;can:Buyer-only&#39;]], function (){<br><br>  Route::get(&#39;/buy/products&#39;, [ProductController::class, &#39;buyProduct&#39;])-&gt;name(&#39;buy.product&#39;);<br><br>});</pre><p><strong><em>I hope you enjoyed this articles , Happy Coding !</em></strong></p><p><strong><em>Next Article : Switch Roles between Seller And Buyer (Both) like fiverr …</em></strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=981fada44554" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>