<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Süleyman Özgür Özarpacı</title>
    <description>The latest articles on DEV Community by Süleyman Özgür Özarpacı (@biostate).</description>
    <link>https://dev.to/biostate</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1060397%2F25325e1f-55b7-41c7-8d99-acd234f70254.jpg</url>
      <title>DEV Community: Süleyman Özgür Özarpacı</title>
      <link>https://dev.to/biostate</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/biostate"/>
    <language>en</language>
    <item>
      <title>Using AI to Help My Girlfriend's Lectures</title>
      <dc:creator>Süleyman Özgür Özarpacı</dc:creator>
      <pubDate>Tue, 30 Dec 2025 11:50:38 +0000</pubDate>
      <link>https://dev.to/biostate/using-ai-to-help-my-girlfriends-lectures-16k2</link>
      <guid>https://dev.to/biostate/using-ai-to-help-my-girlfriends-lectures-16k2</guid>
      <description>&lt;p&gt;My girlfriend has lots of things to study, so I wanted to try to help her. She has lots of notes, lecture videos, and all sorts of medical materials. I decided to choose one topic to test if I could gather all the information into one place and then create a basic quiz about it.&lt;/p&gt;

&lt;p&gt;I started with a video first. The video was 1 hour and 20 minutes long. So watching and creating notes from it would be too hard. Plus, I don't understand most of the medical words. So I had to transcribe it. But the other obstacle was that the video had Turkish, English, and Latin languages at the same time. So I couldn't directly transcribe from English or Turkish or even Latin.&lt;/p&gt;

&lt;p&gt;I researched transcription apps and I found they were too pricey. I don't have that much money for unknown output. So I tried from simple tools to more complicated ones. I used WhisperDesk. It understands but translates to English. Also even the large model wasn't enough to get nice results. Sometimes it got stuck in the same place for no reason. Then I found Speech2Text. I don't want to use a CLI, so there was a GUI at the first place - thanks to open source! I tried it and it did really well at the beginning, but it had the same stuck issue. Maybe the duration of the video was too long? I separated the MP3 file where the teacher was giving a break. Now I had 3 parts. I transcribed them and voilà, it worked.&lt;/p&gt;

&lt;p&gt;Now we had to make it pretty. I removed the timestamps, extra spaces, and made every line a sentence. Then I used Cursor to make it pretty and as a markdown file with topics separated. Also, I asked if some abbreviations or words could be wrong, so fix them based on the context.&lt;/p&gt;

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

&lt;p&gt;Wow, it's been a long journey. I spent 2-3 hours by now, but I did well. Now I checked the notes based on the video part by part and then merged them. Now we had nice context and information. After this, we could use AI to create anything based on the content. I asked Cursor to create a sample quiz page with: text input, true/false or multiple choice questions. Create minimum 30 questions based on the notes. When user gives the answer, immediately show the answer with explanation. Use Bootstrap and don't use custom colors, etc. Use plain Bootstrap. Only create an index.html file.&lt;/p&gt;

&lt;p&gt;You can't believe it, but Cursor again did a very well job. We tried it and we loved it. Now my girlfriend has all the notes and EKG content, has sample quiz questions with explanations, and she can practice as she wants.&lt;/p&gt;

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

&lt;p&gt;This project shows how modern AI tools can make content processing and application development faster and easier. By combining transcription technology, AI content improvement, and automated code generation, I created a complete study solution in just a few hours. The approach demonstrates practical ways to use AI in education technology, making complex content easier to understand and more interactive for students.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
    </item>
    <item>
      <title>How My Medicine Student Girlfriend Completed Simple Development Tasks for Me</title>
      <dc:creator>Süleyman Özgür Özarpacı</dc:creator>
      <pubDate>Sun, 21 Dec 2025 13:35:47 +0000</pubDate>
      <link>https://dev.to/biostate/how-my-medicine-student-girlfriend-completed-simple-development-tasks-for-me-1e94</link>
      <guid>https://dev.to/biostate/how-my-medicine-student-girlfriend-completed-simple-development-tasks-for-me-1e94</guid>
      <description>&lt;p&gt;I have a girlfriend who is studying medicine. She has no background in programming, but she is highly adaptive and curious. One day, I decided to give her some of my development tasks and see what would happen.&lt;/p&gt;

&lt;p&gt;The development environment was already running, so I simply handed my computer to her. I explained at a high level how to interact with the Cursor's UI, how to prompt the AI, and how to review results. After that, I went off to do my chores.&lt;/p&gt;

&lt;p&gt;Some time later, she came back and showed me the result. It was surprisingly acceptable. I reviewed the code and found no major issues. She had even generated an AI-based commit message, which was reasonable, and then committed her first piece of code.&lt;/p&gt;

&lt;p&gt;Encouraged by this, I gave her another task. This one was more complex: it involved APIs, SSR, and Tailwind—in short, a frontend task. It was clearly too large to be solved with a single prompt, so I gave her one key piece of advice:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don’t give the whole task at once. Break it into smaller steps.&lt;br&gt;
Start with a static frontend, then integrate the API, and finally make it SSR-compatible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With that guidance, I went back to my chores.&lt;/p&gt;

&lt;p&gt;When I returned, she had completed the task. Once again, she generated an AI commit message and committed the changes herself.&lt;/p&gt;

&lt;p&gt;She continued this process and completed all five of my tasks in about 1 to 1.5 hours. At the end, she looked at me and said,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Is this your job? You just explain what you need, and after some time it’s done? That’s too easy.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At that point, I had nothing to say.&lt;/p&gt;

&lt;p&gt;She enjoyed “vibe coding,” I finished my chores, and everyone was happy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observations and Reflections
&lt;/h2&gt;

&lt;p&gt;I’m not entirely sure where this fits from an ethical perspective, but I genuinely enjoyed the experience. What made it interesting was not productivity, but observation.&lt;/p&gt;

&lt;p&gt;I was able to see how a non-programmer approaches software development using modern AI-assisted tools. I saw the struggles: understanding abstract concepts, translating vague requirements into concrete steps, and deciding whether the output was actually correct. I also saw the enjoyment: fast feedback, visible progress, and a sense of accomplishment despite having no traditional programming background.&lt;/p&gt;

&lt;p&gt;Watching this process made one thing very clear: the real challenge was never typing code. It was &lt;strong&gt;breaking the problem down&lt;/strong&gt;, sequencing tasks, and knowing when something was “done enough” versus technically correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  A More Realistic Take on AI in Development
&lt;/h2&gt;

&lt;p&gt;I don’t believe that modern software development is shifting from &lt;em&gt;writing code&lt;/em&gt; to &lt;em&gt;directing systems&lt;/em&gt;. That framing feels misleading.&lt;/p&gt;

&lt;p&gt;What I do believe is this: AI is becoming extremely good at helping us solve &lt;strong&gt;well-scoped, basic problems,&lt;/strong&gt; often with one or two prompts. For larger or more complex tasks, it still requires &lt;strong&gt;clear, step-by-step instructions&lt;/strong&gt;. And those instructions do not come from the AI; they come from the engineer.&lt;/p&gt;

&lt;p&gt;In highly abstracted or well-separated projects, you are still the engineer of the system. You define the architecture, the constraints, the trade-offs, and the long-term direction. AI does not replace that role. It acts as a companion.&lt;/p&gt;

&lt;p&gt;A very capable one.&lt;/p&gt;

&lt;p&gt;AI helps by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implementing routine or repetitive code quickly&lt;/li&gt;
&lt;li&gt;Improving existing code through refactoring&lt;/li&gt;
&lt;li&gt;Writing tests and suggesting edge cases&lt;/li&gt;
&lt;li&gt;Surfacing relevant documentation and context&lt;/li&gt;
&lt;li&gt;Bootstrapping features or even entire applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But none of this removes the need for engineering judgment. AI does not understand business context, long-term maintainability, or non-obvious constraints unless those are explicitly provided, and even then, it cannot &lt;em&gt;own&lt;/em&gt; those decisions.&lt;/p&gt;

&lt;p&gt;In practice, AI behaves more like an always-available junior-to-mid-level collaborator. It can move fast, but it still needs guidance, boundaries, and review.&lt;/p&gt;

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

&lt;p&gt;This small experiment reinforced something important for me: AI is not replacing software engineers, but it is reshaping how we work.&lt;/p&gt;

&lt;p&gt;The value of an engineer is increasingly found in problem decomposition, system design, and critical evaluation, not in typing speed or memorizing syntax. When those skills are present, AI becomes a powerful multiplier. When they are not, AI output quickly degrades into noise.&lt;/p&gt;

&lt;p&gt;Seeing a medical student, someone completely outside the software world, successfully complete development tasks was both impressive and grounding. It showed how accessible tooling has become but also highlighted how much invisible expertise still sits behind “simple” instructions.&lt;/p&gt;

&lt;p&gt;And yes, it also means I might outsource more development tasks at home, at least when chores are involved.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>programming</category>
      <category>beginners</category>
      <category>ai</category>
    </item>
    <item>
      <title>How I Use AI Coding Assistants (and How You Can Use Them Better)</title>
      <dc:creator>Süleyman Özgür Özarpacı</dc:creator>
      <pubDate>Thu, 04 Dec 2025 13:01:40 +0000</pubDate>
      <link>https://dev.to/biostate/how-i-use-ai-coding-assistants-and-how-you-can-use-them-better-40af</link>
      <guid>https://dev.to/biostate/how-i-use-ai-coding-assistants-and-how-you-can-use-them-better-40af</guid>
      <description>&lt;p&gt;AI coding assistants have become a hot topic. Some developers say they are terrible and slow them down, while others say AI helps them work faster and reduce mental load. So why is the experience so different? What are some people doing wrong, and what are others doing right?&lt;/p&gt;

&lt;p&gt;This post explains how AI coding assistants actually work, how to give them the right context, and how you can get much better results by improving your prompts and your workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. AI Assistants Work With “Empty Boxes”
&lt;/h2&gt;

&lt;p&gt;AI models are not magical coders who understand your project automatically. They only know what you tell them. Think of each model as an &lt;em&gt;empty box&lt;/em&gt; (its context window). If you don’t fill that box with the &lt;em&gt;correct and relevant&lt;/em&gt; information, the assistant will guess and usually guess wrong.&lt;/p&gt;

&lt;p&gt;Before asking an AI assistant to perform a task, it needs to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your framework and coding standards&lt;/li&gt;
&lt;li&gt;Your project structure&lt;/li&gt;
&lt;li&gt;The purpose of the feature&lt;/li&gt;
&lt;li&gt;Any useful packages or tools&lt;/li&gt;
&lt;li&gt;The current state of your code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Advanced editors like &lt;strong&gt;Cursor&lt;/strong&gt; help here. They inject a high-quality system prompt and index your entire project. Because of that, Cursor can automatically pull relevant files when needed. Your local or basic AI tools probably can’t, because they never receive that system prompt or indexed context.&lt;/p&gt;

&lt;p&gt;But even with advanced tools, you must still give specific instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. “Fix X Feature” Is Not a Prompt
&lt;/h2&gt;

&lt;p&gt;One of the biggest mistakes developers make is giving vague instructions.&lt;br&gt;
For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Improve the UserController.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is too broad. The assistant doesn’t know what “improve” means. Instead, be specific about the problem and the expected solution:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“UserController.php is too large and difficult to maintain. Please refactor it into smaller classes and services based on SOLID principles. Move business logic into services or repositories and keep the controller clean.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This works because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You define the problem&lt;/li&gt;
&lt;li&gt;You describe the desired direction&lt;/li&gt;
&lt;li&gt;You limit the scope&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Give the assistant the same clarity you would give a new teammate.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Give Only the Context That the Task Needs
&lt;/h2&gt;

&lt;p&gt;More context is not always better. If the agent is working on the &lt;strong&gt;payment module&lt;/strong&gt;, you do not need to include the whole report module, notification module, or unrelated controllers. Too much context leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Confused output&lt;/li&gt;
&lt;li&gt;Higher token costs&lt;/li&gt;
&lt;li&gt;Slower responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep context &lt;em&gt;focused&lt;/em&gt;. Let the assistant “build bridges” only when the information is truly related.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Good Prompts Are Detailed and Transparent
&lt;/h2&gt;

&lt;p&gt;If you already know what the error is, or why something is broken, tell the assistant directly. Provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The problem&lt;/li&gt;
&lt;li&gt;The error message&lt;/li&gt;
&lt;li&gt;Log output or stack trace&lt;/li&gt;
&lt;li&gt;The response you expect&lt;/li&gt;
&lt;li&gt;Any constraints or rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don’t lose control when you do this, you gain better results. Don’t be secretive with information you already know.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Choose the Right Model for the Job
&lt;/h2&gt;

&lt;p&gt;You wouldn’t hire a physicist to fix your plumbing. Model selection works the same way.&lt;/p&gt;

&lt;p&gt;Use small models when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tasks are small&lt;/li&gt;
&lt;li&gt;Context needs are minimal&lt;/li&gt;
&lt;li&gt;You want fast and cheap responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use larger models when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tasks are complex&lt;/li&gt;
&lt;li&gt;You need bigger context windows&lt;/li&gt;
&lt;li&gt;You need deep reasoning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don’t always need the biggest or smartest model. You need the right one.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Create Reusable Context Files
&lt;/h2&gt;

&lt;p&gt;To improve your workflow, create a folder like &lt;code&gt;.ai-context/&lt;/code&gt; and add small, organized Markdown files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project structure&lt;/li&gt;
&lt;li&gt;Development rules&lt;/li&gt;
&lt;li&gt;Packages and how they are used&lt;/li&gt;
&lt;li&gt;Environment differences&lt;/li&gt;
&lt;li&gt;Module explanations&lt;/li&gt;
&lt;li&gt;High-level architecture&lt;/li&gt;
&lt;li&gt;System flow diagrams&lt;/li&gt;
&lt;li&gt;Example usages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep the files &lt;strong&gt;small, focused, and non-repetitive&lt;/strong&gt;. Link between files when needed so the assistant can navigate them.&lt;/p&gt;

&lt;p&gt;For example, if you use a library or package:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a small &lt;code&gt;.md&lt;/code&gt; file that explains the library with simple examples.&lt;/li&gt;
&lt;li&gt;Add it to &lt;code&gt;.ai-context/packages/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In your main architecture file, just reference it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This creates a knowledge base the AI can rely on, just like onboarding documentation for new developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Use AI to Improve Your Prompts
&lt;/h2&gt;

&lt;p&gt;If you don’t feel confident in English (B2 or below), ask another AI model to rewrite your prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Please improve this prompt for coding agents.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a simple trick but makes a big difference in code quality.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;AI coding assistants are powerful tools, but only when we use them correctly. They are not mind readers, and they cannot magically understand your entire project without the right context, structure, and guidance. When you give them focused information, clear problems, and well-prepared prompts, they become real partners that can speed up your work and reduce your mental load.&lt;/p&gt;

&lt;p&gt;Remember: be specific, stay organized, give only the context that matters, and choose the right model for the task. Treat the AI like a new teammate who needs directions, not a machine that knows everything. If you build a good system around how you give tasks, you will get reliable, consistent, and high-quality results.&lt;/p&gt;

&lt;p&gt;AI will not replace developers but developers who know how to work with AI will definitely have an advantage.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>tooling</category>
    </item>
    <item>
      <title>How to Fix "The MAC is invalid." Exception in Spatie Permission</title>
      <dc:creator>Süleyman Özgür Özarpacı</dc:creator>
      <pubDate>Mon, 05 May 2025 18:13:59 +0000</pubDate>
      <link>https://dev.to/biostate/how-to-fix-the-mac-is-invalid-exception-in-spatie-permission-39oc</link>
      <guid>https://dev.to/biostate/how-to-fix-the-mac-is-invalid-exception-in-spatie-permission-39oc</guid>
      <description>&lt;p&gt;In many of my Laravel projects, I use Spatie's Permission package alongside encrypted settings to keep sensitive data safe from breaches. However, this can create an issue when you copy production data to a local or staging environment. Since encryption keys differ between environments, attempting to decrypt the settings can result in the following exception:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The MAC is invalid.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This error typically occurs because Laravel is trying to decrypt data that was encrypted with a different application key (&lt;code&gt;APP_KEY&lt;/code&gt;). To solve this, I wrote a custom Artisan command that resets all encrypted setting values to an empty string.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: Reset All Encrypted Setting Values
&lt;/h2&gt;

&lt;p&gt;Here’s the command:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Console\Command&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\File&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Spatie\LaravelSettings\SettingsRepositories\SettingsRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Spatie\LaravelSettings\Support\Crypto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmptyAllEncryptedSettingKeysCommand&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'app:empty-all-encrypted-setting-keys'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Reset all encrypted setting values to an empty string.'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$settingsFolder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;app_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Settings'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;File&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;allFiles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$settingsFolder&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nv"&gt;$settingsRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SettingsRepository&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$files&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$relativePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getRelativePathname&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="nv"&gt;$settingsClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.php'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'\\'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                &lt;span class="s1"&gt;'App\\Settings\\'&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$relativePath&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;class_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$settingsClass&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;method_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$settingsClass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'encrypted'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$settingsClass&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nv"&gt;$settingsRepository&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;updatePropertiesPayload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="nv"&gt;$settingsClass&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Crypto&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
                    &lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'All encrypted setting values have been reset.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Command&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SUCCESS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What Does This Command Do?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It scans all classes under &lt;code&gt;App\Settings\*&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For each class, it checks if it has an &lt;code&gt;encrypted()&lt;/code&gt; method (used to declare encrypted properties).&lt;/li&gt;
&lt;li&gt;It loops through those encrypted keys and replaces their values with an empty encrypted string using &lt;code&gt;Spatie\LaravelSettings&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Helps
&lt;/h2&gt;

&lt;p&gt;When you clone your production database to another environment (e.g., staging or local), any encrypted values cannot be decrypted unless the encryption key (&lt;code&gt;APP_KEY&lt;/code&gt;) matches. Instead of trying to sync keys across environments (which is insecure), it's often safer and easier to just reset encrypted values.&lt;/p&gt;

&lt;p&gt;Running this command prevents "The MAC is invalid." exception and allows you to work with the rest of the settings normally.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
    </item>
    <item>
      <title>How to Trigger Another Action in FilamentPHP</title>
      <dc:creator>Süleyman Özgür Özarpacı</dc:creator>
      <pubDate>Sat, 23 Nov 2024 16:21:52 +0000</pubDate>
      <link>https://dev.to/biostate/how-to-trigger-another-action-in-filamentphp-41hk</link>
      <guid>https://dev.to/biostate/how-to-trigger-another-action-in-filamentphp-41hk</guid>
      <description>&lt;p&gt;If you have an &lt;strong&gt;Action&lt;/strong&gt; in FilamentPHP and want to trigger another action sequentially within it, you can use the &lt;a href="https://filamentphp.com/docs/3.x/actions/adding-an-action-to-a-livewire-component#chaining-actions" rel="noopener noreferrer"&gt;Action Chaining&lt;/a&gt; feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Scenario
&lt;/h2&gt;

&lt;p&gt;Suppose you have an action called &lt;code&gt;DuplicateAction&lt;/code&gt;, and after it completes, you want the &lt;code&gt;EditAction&lt;/code&gt; to open automatically. Below is an example implementation of both actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  EditAction Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you can define the &lt;code&gt;EditAction&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'edit'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;fillForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;$item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;// Your form fields go here&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$arguments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="nv"&gt;$item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  DuplicateAction Example
&lt;/h3&gt;

&lt;p&gt;Here’s how you can define the &lt;code&gt;DuplicateAction&lt;/code&gt; and trigger the &lt;code&gt;EditAction&lt;/code&gt; after duplicating:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'duplicate'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requiresConfirmation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;modalDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Are you sure you want to duplicate this item?'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="nv"&gt;$arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nv"&gt;$isEdit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$arguments&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'edit'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nv"&gt;$item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$newItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;replicate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nv"&gt;$newItem&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$newItem&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;' (copy)'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$newItem&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;afterNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$isEdit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;replaceMountedAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'edit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="s1"&gt;'id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$newItem&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;]);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;extraModalFooterActions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Action&lt;/span&gt; &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;makeModalSubmitAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'duplicateAndEdit'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'edit'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Duplicate and Edit'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;EditAction&lt;/strong&gt;: Opens a form pre-filled with the data of the selected item. When the user submits the form, it updates the item in the database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DuplicateAction&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;Duplicates the selected item and appends " (copy)" to its name.&lt;/li&gt;
&lt;li&gt;Offers an additional button in the modal footer, labeled "Duplicate and Edit," which duplicates the item and directly triggers the &lt;code&gt;EditAction&lt;/code&gt; with the duplicated item's data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By using this method, you can seamlessly open actions sequentially, enhancing the user experience.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>filamentphp</category>
    </item>
    <item>
      <title>Simplifying Asset Updates in FilamentPHP Packages</title>
      <dc:creator>Süleyman Özgür Özarpacı</dc:creator>
      <pubDate>Sat, 23 Nov 2024 14:35:04 +0000</pubDate>
      <link>https://dev.to/biostate/simplifying-asset-updates-in-filamentphp-packages-2pd0</link>
      <guid>https://dev.to/biostate/simplifying-asset-updates-in-filamentphp-packages-2pd0</guid>
      <description>&lt;p&gt;For the past week, I’ve been developing a FilamentPHP package, and this process has taught me quite a bit. However, I’d like to share something with you that I couldn’t find in the documentation.&lt;/p&gt;

&lt;p&gt;When you run &lt;code&gt;npm run dev&lt;/code&gt; during the development of your package, the files are built into the &lt;code&gt;/resources/dist&lt;/code&gt; directory at the root of your package. FilamentPHP then moves these files to the &lt;code&gt;public&lt;/code&gt; directory of your Laravel project when you execute the &lt;code&gt;php artisan filament:assets&lt;/code&gt; command. Therefore, every time you make a change in your FilamentPHP package, you need to run this command in the Laravel project you’re testing on to reflect the updates in the &lt;code&gt;public&lt;/code&gt; directory. &lt;/p&gt;

&lt;p&gt;But what if I told you there’s an easier way? The magic word here is &lt;strong&gt;symlink&lt;/strong&gt; ✨.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checking File Names
&lt;/h3&gt;

&lt;p&gt;First, open the service provider file of your package. For my package, this is the &lt;code&gt;FilamentMenuBuilderServiceProvider.php&lt;/code&gt; file. &lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;getAssets&lt;/code&gt; method, ensure that the exported file name matches the actual file name inside your package. This is crucial because when we create the symlink, the Filament panel will look for the file using the exported name. Since I’m only using a CSS file, my code looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getAssets&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;// WRONG!&lt;/span&gt;
        &lt;span class="nc"&gt;Css&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'filament-menu-builder-styles'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/../resources/dist/filament-menu-builder.css'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

        &lt;span class="c1"&gt;// CORRECT!&lt;/span&gt;
        &lt;span class="nc"&gt;Css&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'filament-menu-builder'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/../resources/dist/filament-menu-builder.css'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more information, please read the &lt;a href="https://filamentphp.com/docs/3.x/support/assets#registering-assets-for-a-plugin" rel="noopener noreferrer"&gt;documention&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating a Symlink
&lt;/h3&gt;

&lt;p&gt;The process of creating a symlink varies depending on your operating system. Since I’m using Windows, I utilize &lt;a href="https://schinagl.priv.at/nt/hardlinkshellext/linkshellextension.html" rel="noopener noreferrer"&gt;Link Shell Extension&lt;/a&gt; for this purpose.&lt;/p&gt;

&lt;p&gt;I symlink the &lt;code&gt;/resources/dist&lt;/code&gt; directory to &lt;code&gt;/public/css/{vendor_name}/{package_name}&lt;/code&gt; in my Laravel project. For my project, this would be &lt;code&gt;/public/css/biostate/filament-builder&lt;/code&gt;. From now on, any changes in the &lt;code&gt;dist&lt;/code&gt; folder of my package will automatically reflect in the &lt;code&gt;public&lt;/code&gt; directory of my Laravel project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;By leveraging symlinks, you can significantly streamline your development process for FilamentPHP packages. This eliminates the repetitive task of running &lt;code&gt;php artisan filament:assets&lt;/code&gt; after every change, allowing you to focus more on building and less on manual updates.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>filamentphp</category>
    </item>
    <item>
      <title>Throwing Success or Failure Notifications Manually in FilamentPHP Actions</title>
      <dc:creator>Süleyman Özgür Özarpacı</dc:creator>
      <pubDate>Sat, 09 Nov 2024 23:47:47 +0000</pubDate>
      <link>https://dev.to/biostate/throwing-success-or-failure-notifications-manually-in-filamentphp-actions-1gkn</link>
      <guid>https://dev.to/biostate/throwing-success-or-failure-notifications-manually-in-filamentphp-actions-1gkn</guid>
      <description>&lt;p&gt;When developing with Filament, there are times when you might need to display success or failure notifications based on the results of an action. Using &lt;code&gt;success&lt;/code&gt; and &lt;code&gt;failure&lt;/code&gt; methods allows you to manage these notifications manually, giving more control over how and when messages are shown to users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Create the Base &lt;code&gt;Action&lt;/code&gt; Code
&lt;/h2&gt;

&lt;p&gt;Let's start by creating a base &lt;code&gt;Action&lt;/code&gt; that will display a modal with specific input fields. This example sets up an action called "Regenerate Media Conversions," with a form where users can specify options for media conversion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Regenerate Media Conversions'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;requiresConfirmation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;modalWidth&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2xl'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;form&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="nc"&gt;Select&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'media'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;options&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'All'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Only Products'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;Category&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Only Categories'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;]),&lt;/span&gt;
        &lt;span class="nc"&gt;TextInput&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ids'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'1,2,3,4,5'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Checkbox&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'only_missing'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nc"&gt;Checkbox&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'with_responsive_images'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="cm"&gt;/* Perform your specific action here */&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code creates a modal with a form containing fields for media selection, IDs, and additional options. With these inputs, you can then customize and perform any necessary tasks, such as regenerating media conversions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Set Success and Failure Titles
&lt;/h2&gt;

&lt;p&gt;To make sure notifications appear upon success or failure, set the titles for these messages using the &lt;code&gt;successNotificationTitle&lt;/code&gt; and &lt;code&gt;failureNotificationTitle&lt;/code&gt; methods. Without these, no notifications will be shown even if the action succeeds or fails.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Regenerate Media Conversions'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="mf"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;successNotificationTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Process started. You will be notified.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;failureNotificationTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Process failed.'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Modify the &lt;code&gt;action&lt;/code&gt; Method to Trigger Notifications
&lt;/h2&gt;

&lt;p&gt;Now, let's update the &lt;code&gt;action&lt;/code&gt; method to actually throw the &lt;code&gt;success&lt;/code&gt; or &lt;code&gt;failure&lt;/code&gt; notifications. Here’s how to handle both cases within a try-catch block.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Regenerate Media Conversions'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="mf"&gt;...&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt; &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;/* Perform your specific action */&lt;/span&gt;
            &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;success&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Trigger success notification&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;\Exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;failure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Trigger failure notification&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Customizing Success or Failure Messages
&lt;/h2&gt;

&lt;p&gt;If you need to dynamically adjust the success or failure messages based on certain conditions, use the &lt;code&gt;successNotificationTitle&lt;/code&gt; and &lt;code&gt;failureNotificationTitle&lt;/code&gt; methods within the &lt;code&gt;action&lt;/code&gt; function. For instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Action&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Regenerate Media Conversions'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Action&lt;/span&gt; &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="cm"&gt;/* Perform your specific action */&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$isQueued&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;successNotificationTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Process queued successfully.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;successNotificationTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Process started immediately.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;success&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Trigger success notification&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;\Exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;failureNotificationTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Process failed with error: '&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;getMessage&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
            &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;failure&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Trigger failure notification&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach enables you to display custom messages for both queued and non-queued processes, as well as detailed error information if the action fails.&lt;/p&gt;

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

&lt;p&gt;By manually setting &lt;code&gt;success&lt;/code&gt; and &lt;code&gt;failure&lt;/code&gt; notifications in Filament actions, you gain control over the feedback displayed to users, allowing for customized messages based on specific conditions or outcomes. This not only enhances user experience but also improves clarity when things go right or wrong.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>filamentphp</category>
    </item>
    <item>
      <title>How to Minify and Cache CSS &amp; JS Files in Laravel</title>
      <dc:creator>Süleyman Özgür Özarpacı</dc:creator>
      <pubDate>Mon, 21 Oct 2024 10:00:00 +0000</pubDate>
      <link>https://dev.to/biostate/how-to-minify-and-cache-css-js-files-in-laravel-8nm</link>
      <guid>https://dev.to/biostate/how-to-minify-and-cache-css-js-files-in-laravel-8nm</guid>
      <description>&lt;p&gt;In modern web development, speed and performance are crucial for delivering a seamless user experience. One of the most effective techniques for optimizing performance is minification. Minification involves removing unnecessary characters from CSS and JavaScript files—such as whitespace, comments, and line breaks—without affecting their functionality. This process reduces file sizes, leading to faster load times, lower bandwidth consumption, and an overall improved user experience, especially for those on slower networks.&lt;/p&gt;

&lt;p&gt;While tools like Laravel Mix or Vite are often used to manage and optimize assets, there are scenarios where these tools may not be applicable—such as when working with files provided by users or external sources. In such cases, manual optimization becomes necessary. In this article, we'll demonstrate how to optimize and stream these files directly using PHP, focusing on implementing minification in a Laravel project with the help of the &lt;code&gt;matthiasmullie/minify&lt;/code&gt; package.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install the &lt;code&gt;matthiasmullie/minify&lt;/code&gt; Package
&lt;/h3&gt;

&lt;p&gt;To get started, install the &lt;code&gt;matthiasmullie/minify&lt;/code&gt; package via Composer. This package provides a simple API for minifying both CSS and JavaScript files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require matthiasmullie/minify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Create a Minification Route
&lt;/h3&gt;

&lt;p&gt;Next, add the following route to your &lt;code&gt;web.php&lt;/code&gt; file. This route will handle requests to minify any CSS or JS file and serve the minified content, caching the result for improved performance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Cache&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;MatthiasMullie\Minify\CSS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;MatthiasMullie\Minify\JS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;Route&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'minify/{any}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;public_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$any&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Cache the checksum of the file&lt;/span&gt;
    &lt;span class="nv"&gt;$checksum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;remember&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"file_checksum:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;365&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;md5_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Cache the file content based on the checksum&lt;/span&gt;
    &lt;span class="nv"&gt;$content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;remember&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"file_content:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$checksum&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;365&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$extension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;pathinfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;PATHINFO_EXTENSION&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$extension&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s1"&gt;'css'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
                &lt;span class="nv"&gt;$minifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CSS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nv"&gt;$minifiedContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$minifier&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;minify&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$minifiedContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'headers'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'text/css'&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s1"&gt;'js'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
                &lt;span class="nv"&gt;$minifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="nv"&gt;$minifiedContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$minifier&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;minify&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$minifiedContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'headers'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'application/javascript'&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
            &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s1"&gt;'headers'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'Content-Type'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'text/plain'&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Set content and headers&lt;/span&gt;
    &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'headers'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="c1"&gt;// Set Cache-Control, Expires and ETag headers for browser caching&lt;/span&gt;
    &lt;span class="nv"&gt;$cacheDuration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;365&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1 year in minutes&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Cache-Control'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"public, max-age="&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cacheDuration&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Expires'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addMinutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$cacheDuration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;toRfc7231String&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ETag'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$checksum&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ETag for validation&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'any'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.*'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'themes_file'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Usage
&lt;/h3&gt;

&lt;p&gt;Once you've followed the steps above, you can start using the minification feature by updating your HTML references. For example, if you have the following CSS and JavaScript references:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&amp;lt;&lt;span class="nb"&gt;link &lt;/span&gt;&lt;span class="nv"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"stylesheet"&lt;/span&gt; &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/css/style.css"&lt;/span&gt;/&amp;gt;
&amp;lt;script &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"text/javascript"&lt;/span&gt; &lt;span class="nv"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"js/main.js"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will need to modify them to point to the minified versions as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&amp;lt;&lt;span class="nb"&gt;link &lt;/span&gt;&lt;span class="nv"&gt;rel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"stylesheet"&lt;/span&gt; &lt;span class="nv"&gt;href&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/minify/css/style.css"&lt;/span&gt;/&amp;gt;
&amp;lt;script &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"text/javascript"&lt;/span&gt; &lt;span class="nv"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/minify/js/main.js"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the first request, your CSS and JavaScript files will be minified and cached within your application. Additionally, the user's browser will cache these files, significantly reducing load times on subsequent visits. This caching mechanism ensures both server-side and client-side performance improvements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Key Considerations
&lt;/h3&gt;

&lt;p&gt;This route performs two main tasks: it minifies the requested file (CSS or JS) and caches the result for quicker responses in future requests. The use of &lt;strong&gt;ETag&lt;/strong&gt; and &lt;strong&gt;Cache-Control&lt;/strong&gt; headers ensures that the browser can cache these assets for up to one year, reducing server load and speeding up content delivery.&lt;/p&gt;

&lt;p&gt;However, this is just a basic implementation. To improve readability and maintainability, you can further optimize the code using design patterns like the &lt;strong&gt;Strategy Pattern&lt;/strong&gt; or leverage a more robust asset management tool. Laravel Mix or other bundlers like Webpack can also be integrated for more complex use cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Minification is a simple yet effective way to boost your website's performance by reducing file sizes and improving load times. With Laravel and the &lt;code&gt;matthiasmullie/minify&lt;/code&gt; package, you can quickly implement minification and caching for your CSS and JavaScript files. While this article demonstrates a basic implementation, consider exploring more advanced optimizations and design patterns to ensure your application remains maintainable as it scales.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Change Local Storage Path in Laravel</title>
      <dc:creator>Süleyman Özgür Özarpacı</dc:creator>
      <pubDate>Wed, 02 Oct 2024 19:00:06 +0000</pubDate>
      <link>https://dev.to/biostate/how-to-change-local-storage-path-in-laravel-30en</link>
      <guid>https://dev.to/biostate/how-to-change-local-storage-path-in-laravel-30en</guid>
      <description>&lt;p&gt;In Laravel, there may be instances where you need to change your storage path to accommodate specific requirements. For example, in my case, I encountered an issue with insufficient disk space for my projects. To resolve this, I purchased a DigitalOcean Volume to expand my storage capacity. In this article, I will demonstrate two methods to modify your storage path effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Volume
&lt;/h2&gt;

&lt;p&gt;To begin, log in to your DigitalOcean account and navigate to the Droplets section. Select your droplet, then go to the Volumes tab. From there, create a new volume, specifying the size according to your storage requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server Configuration
&lt;/h2&gt;

&lt;p&gt;Since I am using Laravel Forge, I need to connect to the server via SSH to verify that the volume has been successfully attached to my droplet. Use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh forge@[YOUR_IP_ADDRESS]
lsblk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Find the disk you added from the list. In our setup, the disk appears as &lt;code&gt;volume_fra1_01&lt;/code&gt;, and its mount path is &lt;code&gt;/mnt/volume_fra1_01&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next, create a storage folder for your application within the new volume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; /mnt/volume_fra1_01/[app_name]_storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you already have an existing storage folder, copy its contents to the newly created folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; /var/www/your_laravel_project/storage /mnt/volume_fra1_01/[app_name]_storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a precaution, in case anything goes wrong, rename the original storage folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mv &lt;/span&gt;storage backup_storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the newly created folder resides under the root user, update its permissions to those recommended by Laravel, and change the owner to forge:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; forge:forge /mnt/volume_fra1_01/[app_name]_storage
&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 755 /mnt/volume_fra1_01/[app_name]_storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Application Configuration
&lt;/h2&gt;

&lt;p&gt;At this stage, you have two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update without modifying the application by creating a symlink.&lt;/li&gt;
&lt;li&gt;Change the storage path within the application itself.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Option 1: Using a Symlink (The Most Stable Method)
&lt;/h3&gt;

&lt;p&gt;Navigate to the root directory of your application and create a symlink for the new storage directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd [your_laravel_project_path]
ln -s /mnt/volume_fra1_01/[app_name]_storage/ storage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Option 2: Modifying the Application
&lt;/h3&gt;

&lt;p&gt;To update the storage path within the application, add the following code to the boot method of your &lt;code&gt;AppServiceProvider.php&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;useStoragePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app.app_storage_path'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, add this line to your &lt;code&gt;app.php&lt;/code&gt; configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="c1"&gt;// Your other configurations&lt;/span&gt;
    &lt;span class="s1"&gt;'app_storage_path'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'APP_STORAGE_PATH'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;base_path&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="mf"&gt;.&lt;/span&gt;&lt;span class="s1"&gt;'/storage'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// Add this line&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One of the most common mistakes made during this process is directly using the &lt;code&gt;env()&lt;/code&gt; method in the application without adding the corresponding value to &lt;code&gt;app.php&lt;/code&gt;. If you do this, when you run &lt;code&gt;config:cache&lt;/code&gt;, the &lt;code&gt;env()&lt;/code&gt; method will always return &lt;code&gt;null&lt;/code&gt;, causing your application to malfunction. Therefore, I highly recommend that for every value you add to the &lt;code&gt;.env&lt;/code&gt; file, you also define a corresponding entry in a configuration file to ensure proper functionality.&lt;/p&gt;

&lt;p&gt;If you've added the above code, you can now dynamically change your application's storage path by adding the &lt;code&gt;APP_STORAGE_PATH&lt;/code&gt; value to your &lt;code&gt;.env&lt;/code&gt; file. If you don't add this value, the application will default to using the storage folder in your root directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;APP_STORAGE_PATH="/mnt/volume_fra1_01/[app_name]_storage" # &amp;lt;-- Use this value to change your storage path

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Option 2 may cause errors depending on the packages, code structure, or features you use in your application. If you choose this method, I strongly recommend running your tests and manually checking your application afterward.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;To finalize, ensure that you clear all cached data by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan optimize:clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By following these steps, you now have the flexibility to update your storage path as needed, allowing your application to leverage any desired disk for file storage. This method provides enhanced adaptability and scalability, ensuring your Laravel application can continue to grow alongside your storage requirements.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>digitalocean</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>Turn Your MySQL to Case Sensitivity on Windows</title>
      <dc:creator>Süleyman Özgür Özarpacı</dc:creator>
      <pubDate>Mon, 15 Apr 2024 17:47:32 +0000</pubDate>
      <link>https://dev.to/biostate/turn-your-mysql-to-case-sensitivity-on-windows-22n5</link>
      <guid>https://dev.to/biostate/turn-your-mysql-to-case-sensitivity-on-windows-22n5</guid>
      <description>&lt;p&gt;When working with MySQL on Windows, you might notice that table names are not case-sensitive by default. This is because the Windows file system is case-insensitive, unlike Linux or macOS, which can lead to unexpected behavior if your development or production environment depends on case-sensitive table names. In my case, I am using Windows 11, and I needed to enable case sensitivity for a project where I need to ensure that User and user are treated as distinct table names. Here’s how I achieved that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Locate Your MySQL Configuration File
&lt;/h2&gt;

&lt;p&gt;The first step in making MySQL case-sensitive is to modify the MySQL configuration file (my.ini). Depending on how MySQL is installed on your machine, the path to this file can vary. In my case, I'm using Laragon, so my configuration file is located here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C:\laragon\bin\mysql\mysql-8.0.13-winx64\my.ini
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will need to open this file with a text editor like Notepad or an IDE of your choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Modify the my.ini Configuration
&lt;/h2&gt;

&lt;p&gt;Once you've opened the my.ini file, search for the &lt;code&gt;[mysqld]&lt;/code&gt; section. This is where you will add a new configuration line to enable case sensitivity. Insert the following line directly under the &lt;code&gt;[mysqld]&lt;/code&gt; header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lower_case_table_names=0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setting tells MySQL to preserve the case of table names, making the database case-sensitive. By default, on Windows, the value is 1, which means MySQL converts all table names to lowercase, regardless of how they are defined.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Adjusting the Windows File System
&lt;/h2&gt;

&lt;p&gt;Although adding the above configuration enables MySQL to respect case sensitivity, there’s one important thing to note: the Windows file system is inherently case-insensitive. That means even with &lt;code&gt;lower_case_table_names=0&lt;/code&gt;, your file system will still treat User and user as the same file or folder, leading to potential issues.&lt;/p&gt;

&lt;p&gt;To overcome this limitation, you need to configure the Windows file system to support case-sensitive directories. This requires some additional steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Enable Case Sensitivity in Windows
&lt;/h2&gt;

&lt;p&gt;You will need to enable case sensitivity for the folder where MySQL stores your database files. This folder is typically located under your MySQL installation's data directory. In my setup, it’s located here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;C:\laragon\data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before proceeding, I recommend making a backup of all your existing database files and folders in case anything goes wrong. Once that’s done, you can enable case sensitivity for this folder by running the following command in an elevated Command Prompt (run as Administrator):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fsutil.exe file SetCaseSensitiveInfo C:\laragon\data enable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command tells Windows to enable case sensitivity for the specified directory, which is crucial for MySQL to handle table names in a case-sensitive manner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Restart MySQL
&lt;/h2&gt;

&lt;p&gt;After making the above changes, you should restart the MySQL service for the new configuration to take effect. If everything is set up correctly, MySQL should now treat User and user as two separate tables, just like it would on a case-sensitive file system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Enabling case sensitivity on MySQL in Windows can be tricky due to the underlying nature of the Windows file system, but by following the steps outlined above, you should be able to achieve the desired behavior. Remember that while this works well for development environments, it's always a good idea to match your production environment closely to avoid any surprises when deploying your application.&lt;/p&gt;

&lt;p&gt;For more details on this topic, check out the following resources:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/answers/questions/994555/case-sensitive-table-names-in-mysql" rel="noopener noreferrer"&gt;Case-Sensitive Table Names in MySQL&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.ortussolutions.com/blog/how-to-make-windows-folders-case-sensitive" rel="noopener noreferrer"&gt;How to Make Windows Folders Case-Sensitive&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.skeema.io/blog/2022/06/07/lower-case-table-names/" rel="noopener noreferrer"&gt;Managing MySQL Lower Case Table Names&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mysql</category>
      <category>laragon</category>
    </item>
    <item>
      <title>Theme Management in Laravel</title>
      <dc:creator>Süleyman Özgür Özarpacı</dc:creator>
      <pubDate>Wed, 13 Sep 2023 16:49:37 +0000</pubDate>
      <link>https://dev.to/biostate/theme-management-in-laravel-1l03</link>
      <guid>https://dev.to/biostate/theme-management-in-laravel-1l03</guid>
      <description>&lt;p&gt;At times, you may find the need to manage themes in your Laravel project. For this purpose, the &lt;a href="https://github.com/hexadog/laravel-themes-manager" rel="noopener noreferrer"&gt;&lt;code&gt;hexadog/laravel-themes-manager&lt;/code&gt;&lt;/a&gt; package will fulfill your requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works?
&lt;/h2&gt;

&lt;p&gt;The algorithm behind this package is elegantly simple yet remarkably powerful. It seamlessly integrates your theme path into Laravel's default View Finder paths, revolutionizing your ability to manage and customize views.&lt;/p&gt;

&lt;p&gt;The View Finder carries out its search for views in the following order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It first looks in the current theme's designated path.&lt;/li&gt;
&lt;li&gt;If the current theme has a parent theme, it extends its search to include the parent theme's path.&lt;/li&gt;
&lt;li&gt;As a fallback, it checks Laravel's default resources/views folder.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This versatile package also empowers you to override third-party package vendor files and error views with ease. You have the flexibility to create custom views for specific scenarios, such as &lt;code&gt;errors/404.blade.php&lt;/code&gt; or &lt;code&gt;vendor/mail/notifications/email.blade.php&lt;/code&gt;, tailored to each theme's unique requirements.&lt;/p&gt;

&lt;p&gt;For more detailed information on how this works and utilizing views effectively, you can refer to the following resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://laravel-themes-manager.netlify.app/1.10/how-it-works.html#theme-structure" rel="noopener noreferrer"&gt;How it Works&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://laravel-themes-manager.netlify.app/1.10/usage/views.html#errors-views" rel="noopener noreferrer"&gt;Views&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Child Theme Support
&lt;/h2&gt;

&lt;p&gt;The child theme feature enables your theme to inherit properties and functionality from a parent theme. By utilizing this feature, your child theme becomes dependent on the parent theme, allowing for efficient theme customization.&lt;/p&gt;

&lt;p&gt;For instance, let's say you've developed a theme named &lt;code&gt;default/example&lt;/code&gt;, and you need to introduce modifications like a simplified product listing or different color schemes. In such cases, creating a child theme becomes essential. You can easily create a child theme named &lt;code&gt;default/example-simple&lt;/code&gt; and proceed to add specific elements like the &lt;code&gt;components/product-list-item.blade.php&lt;/code&gt; view.&lt;/p&gt;

&lt;p&gt;With this setup, the theme manager prioritizes the views within your child theme, utilizing them instead of the parent theme's defaults. If the theme manager doesn't find a particular element in your child theme, it gracefully falls back to the parent theme, ensuring a seamless and flexible theme management experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;Please follow &lt;a href="https://github.com/hexadog/laravel-themes-manager#installation" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; to setup package.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Theme
&lt;/h2&gt;

&lt;p&gt;The package includes a vendor prefix at the beginning of your theme name, ensuring that theme names remain unique. This vendor name serves as a differentiator, allowing you to create themes like &lt;code&gt;commerce/example&lt;/code&gt; and &lt;code&gt;commerce-b2b/example&lt;/code&gt;. While the theme names may appear the same, they reside in distinct vendor namespaces, preventing conflicts.&lt;/p&gt;

&lt;p&gt;Creating a new theme is an effortless process. Simply execute the following command and provide the necessary inputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan theme:make
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates these files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;themes
    ├── vendorName
    │   ├── themeName
    │   │   ├── public
    │   │   │   ├── css
    │   │   │   ├── js
    │   │   │   ├── img
    │   │   └── resources
    │   │   │   ├── views
    │   │   │   │   ├── layouts
    │   │   │   │   │   └── app.blade.php
    │   │   │   │   │   └── guest.blade.php
    │   │   └── composer.json
    │   └── ...
    └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using Themes
&lt;/h2&gt;

&lt;p&gt;You have the flexibility to incorporate themes either within a controller or as part of a middleware. To seamlessly integrate theme logic into your Laravel project, you can refer to the following documentation pages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://laravel-themes-manager.netlify.app/1.10/usage/basic.html" rel="noopener noreferrer"&gt;Using Themes in Controllers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://laravel-themes-manager.netlify.app/1.10/usage/middleware.html" rel="noopener noreferrer"&gt;Using Themes in Middleware&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These resources provide detailed guidance on implementing themes to enhance the visual and functional aspects of your application.&lt;/p&gt;

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

&lt;p&gt;Embracing theme management in your Laravel project with the &lt;a href="https://github.com/hexadog/laravel-themes-manager" rel="noopener noreferrer"&gt;&lt;code&gt;hexadog/laravel-themes-manager&lt;/code&gt;&lt;/a&gt; package opens up exciting possibilities for customization. You can effortlessly create themes, enhance views, and seamlessly apply them in controllers or middleware. Whether you're building a complex e-commerce site or a straightforward blog, this package simplifies the theme integration process, making it a valuable asset for Laravel developers. Start exploring theme management today to take your Laravel projects to the next level of visual and functional excellence.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
    </item>
    <item>
      <title>How to Stop FilamentPHP Actions On Certain Conditions</title>
      <dc:creator>Süleyman Özgür Özarpacı</dc:creator>
      <pubDate>Sun, 06 Aug 2023 00:58:30 +0000</pubDate>
      <link>https://dev.to/biostate/how-to-stop-filamentphp-actions-2ipd</link>
      <guid>https://dev.to/biostate/how-to-stop-filamentphp-actions-2ipd</guid>
      <description>&lt;p&gt;In some cases, FilamentPHP processes need to be stopped based on certain conditions. To achieve this, we can use the &lt;code&gt;cancel()&lt;/code&gt;method of an action. This article demonstrates how to use &lt;code&gt;cancel()&lt;/code&gt; effectively and includes notifications to provide meaningful feedback to users.&lt;/p&gt;

&lt;p&gt;You can also use &lt;code&gt;halt()&lt;/code&gt; but halt does not close modals.&lt;/p&gt;

&lt;p&gt;Example Scenario:&lt;br&gt;
Consider a scenario where we want to prevent force-deleting a user if they have active orders. We will use a ForceDeleteBulkAction and its before callback to perform the necessary checks and notify the user accordingly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Tables\Actions\ForceDeleteBulkAction&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$records&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Tables&lt;/span&gt;&lt;span class="nc"&gt;\Actions\ForceDeleteBulkAction&lt;/span&gt; &lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// code goes here&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checking for Active Orders and Canceling the Process:&lt;br&gt;
To check for active orders, query the relevant data and cancel the process if any orders are found. We can achieve this as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;Tables\Actions\ForceDeleteBulkAction::make()
&lt;/span&gt;    -&amp;gt;before(
        function ($records, Tables\Actions\ForceDeleteBulkAction $action) {
&lt;span class="gi"&gt;+            $ids = $records-&amp;gt;pluck('id')-&amp;gt;toArray();
+            $exists = Order::whereIn('user_id', $ids)-&amp;gt;exists();
+            if ($exists) {
+                $action-&amp;gt;cancel();
+            }
&lt;/span&gt;        }
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cancel does not show notification about why process canceled. Use &lt;a href="https://filamentphp.com/docs/2.x/notifications/sending-notifications" rel="noopener noreferrer"&gt;Notification&lt;/a&gt; documentation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gi"&gt;+use Filament\Notifications\Notification;
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="p"&gt;Tables\Actions\ForceDeleteBulkAction::make()
&lt;/span&gt;    -&amp;gt;before(
        function ($records, Tables\Actions\ForceDeleteBulkAction $action) {
            $ids = $record-&amp;gt;orders()-&amp;gt;pluck('id')-&amp;gt;toArray();
            $exists = Order::whereIn('user_id', $ids)-&amp;gt;exists();
            if ($exists) {
&lt;span class="gi"&gt;+                Notification::make()
+                    -&amp;gt;title('Errors!')
+                    -&amp;gt;body("You can't force delete users because someone has orders.")
+                    -&amp;gt;status('danger')
+                    -&amp;gt;send();
&lt;/span&gt;                $action-&amp;gt;cancel();
           }
        }
    )
&lt;span class="err"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By using the cancel() method in FilamentPHP, we can effectively halt an action based on specific conditions. In the example provided, we prevent force-deleting users with active orders and enhance the user experience by sending a notification explaining the reason for the process cancellation. This approach ensures that users are informed about the constraints and can take appropriate actions accordingly.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>filamentphp</category>
    </item>
  </channel>
</rss>
