<?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>Forem: Francis Ilechukwu</title>
    <description>The latest articles on Forem by Francis Ilechukwu (@thefullstackjonin).</description>
    <link>https://forem.com/thefullstackjonin</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%2F93891%2F5c669c78-8dca-49c7-9cb3-23bdd0d2f39c.png</url>
      <title>Forem: Francis Ilechukwu</title>
      <link>https://forem.com/thefullstackjonin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/thefullstackjonin"/>
    <language>en</language>
    <item>
      <title>Getting Readable Crash Reports in Firebase Crashlytics from your Flutter Application</title>
      <dc:creator>Francis Ilechukwu</dc:creator>
      <pubDate>Wed, 14 Aug 2024 00:38:00 +0000</pubDate>
      <link>https://forem.com/thefullstackjonin/getting-readable-crash-reports-in-firebase-crashlytics-from-your-flutter-application-1pp0</link>
      <guid>https://forem.com/thefullstackjonin/getting-readable-crash-reports-in-firebase-crashlytics-from-your-flutter-application-1pp0</guid>
      <description>&lt;h2&gt;
  
  
  Table Of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Android&lt;/li&gt;
&lt;li&gt;iOS&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Introduction &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Many of us have deployed mobile applications to pre-production/production environments and got an email from Firebase saying "Heads up! We detected a new fatal issue in !" if you integrated Firebase crashlytics.&lt;/p&gt;

&lt;p&gt;You wonder what it could be about, and head over to the firebase console under the crashlytics section to find out nothing makes sense, everything looks like a hexadecimal fest.&lt;/p&gt;

&lt;p&gt;In this article, we'll look at steps to take for both Android &amp;amp; iOS applications built with Flutter to ensure our crash reports are readable for every app version we release.&lt;/p&gt;

&lt;p&gt;Before we get into it, Flutter is an open-source cross-platform development kit that supports but is not limited to Android and iOS and will generate binaries for these platforms when instructed to.&lt;/p&gt;

&lt;p&gt;These binaries may be in &lt;code&gt;.aab&lt;/code&gt; or &lt;code&gt;.apk&lt;/code&gt; format for Android and in &lt;code&gt;.ipa&lt;/code&gt; for iOS. &lt;/p&gt;

&lt;p&gt;It's safe to say that if you stumbled upon this article, you already understand what &lt;a href="https://www.zimperium.com/obfuscation/" rel="noopener noreferrer"&gt;obfuscation&lt;/a&gt; means&lt;/p&gt;

&lt;p&gt;In any case, obfuscation is a means by which during the compilation of an application, the resulting symbols or tokens that you as the developer understand and can make meaning of in the first instance, are obscured. i.e. functions, classes, and variable names will be rendered meaning less, thus making it extremely hard to reverse-engineer. This is a security measure that production-grade applications go through.&lt;/p&gt;

&lt;p&gt;This is why stack traces or error messages on the crashlytics dashboards are a bunch of gibberish without the steps we will go into detail on.&lt;/p&gt;

&lt;p&gt;If Firebase crashlytics was set up properly, you probably don't need to read this article. But for some wired reason, I've set up a couple of Flutter applications with Firebase crashlytics following all the steps in the official documentation and I still get the warning for missing dSYM files for iOS even though there are build steps that are meant to take care of this. If you are in the same situation, then read on.&lt;/p&gt;

&lt;p&gt;Before we proceed, I assume that you've already integrated Firebase crashlytics with your Flutter application for Android and iOS. If you've not done that, See &lt;a href="https://firebase.google.com/docs/crashlytics/get-started?platform=flutter" rel="noopener noreferrer"&gt;Integrating Firebase Crashlytics with your Fluter Application&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Android &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;When developing Android applications using Flutter and you want obfuscation enabled, you'd pass the &lt;code&gt;--obfuscate&lt;/code&gt; flag and the &lt;code&gt;--split-debug-info&lt;/code&gt; argument. The &lt;code&gt;--split-debug-info&lt;/code&gt; flag is the most important argument for what we want to achieve as this tells the flutter binary where to output the debug symbols files. &lt;/p&gt;

&lt;p&gt;We'll upload these files to Firebase using the Firebase CLI tool.&lt;/p&gt;

&lt;p&gt;Here's a full flutter build command that obfuscates the resulting application and outputs the debug symbols to a specified path&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flutter build apk &lt;span class="nt"&gt;--target-platform&lt;/span&gt; android-arm,android-arm64,android-x64 &lt;span class="nt"&gt;--release&lt;/span&gt; &lt;span class="nt"&gt;--obfuscate&lt;/span&gt; &lt;span class="nt"&gt;--split-debug-info&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;build/app/outputs/symbols &lt;span class="nt"&gt;--verbose&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we've told Flutter to output debug symbols to the path &lt;code&gt;build/app/outputs/symbols&lt;/code&gt;. Note that the path will be created if it doesn't exist.&lt;/p&gt;

&lt;p&gt;The next step is to use the Firebase CLI tool. If you don't have it installed, use the below command to do so&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sL&lt;/span&gt; https://firebase.tools | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then use the below to log in to your Firebase account&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To upload the debug symbols, you then use the command below while pointing to the folder containing the debug symbols&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase crashlytics:symbols:upload &lt;span class="nt"&gt;--app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;FIREBASE_APP_ID build/app/outputs/symbols
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can obtain &lt;code&gt;FIREBASE_APP_ID&lt;/code&gt; from your 'Project Settings' page in  the Firebase console as shown below&lt;/p&gt;

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

&lt;p&gt;If running the &lt;code&gt;firebase crashlytics:symbols:upload&lt;/code&gt; command in a CI environment like GitHub Actions, set an environment variable &lt;code&gt;GOOGLE_APPLICATION_CREDENTIALS&lt;/code&gt; to point to the location of your service account &lt;code&gt;.json&lt;/code&gt; key file.&lt;/p&gt;

&lt;p&gt;Below is a typical re-usable and manually dispatchable GitHub Actions workflow that downloads the symbols folder as a zipped artifact, extracts it, and uploads it to Firebase. the workflow is expected to be re-used by an actual job in a workflow consisting of other jobs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;upload-flutter-debug-symbols-to-firebase&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;flutter-debug-symbols-artifact-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AAB Artifact Name.&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
  &lt;span class="na"&gt;workflow_call&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;flutter-debug-symbols-artifact-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AAB Artifact Name.&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
    &lt;span class="na"&gt;secrets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;FIREBASE_APP_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Firebase App ID&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="na"&gt;FIREBASE_SERVICE_ACCOUNT_JSON_CONTENT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Firebase Service Account Key Content&lt;/span&gt;
        &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;upload-debug-symbols&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload Flutter Debug Symbols to Firebase&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Firebase Tools&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;curl -sL https://firebase.tools | bash&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Download Flutter Debug Symbols&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/download-artifact@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ inputs.flutter-debug-symbols-artifact-name }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Extract Flutter Debug Symbols&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unzip -q ./symbols.zip -d symbols&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Prepare Google Service Account Credential&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo '${{ secrets.FIREBASE_SERVICE_ACCOUNT_JSON_CONTENT }}' &amp;gt;&amp;gt; firebase-service-account.json&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload Flutter Debug Symbols to Firebase&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GOOGLE_APPLICATION_CREDENTIALS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;firebase-service-account.json&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;firebase crashlytics:symbols:upload --app=${{ secrets.FIREBASE_APP_ID }} ./symbols&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  iOS &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Running the &lt;code&gt;flutterfire configure&lt;/code&gt; command after &lt;a href="https://firebase.google.com/docs/crashlytics/get-started?platform=flutter" rel="noopener noreferrer"&gt;integrating&lt;/a&gt; your Flutter project with Firebase crashlytics will attempt to add a run script to your project’s Xcode workspace that finds and uploads the necessary dSYM symbol files to Crashlytics. Without these files, you’ll see a "Missing dSYM" alert in the Crashlytics dashboard and exceptions will be held by the backend until the missing files are uploaded - &lt;a href="https://firebase.google.com/docs/crashlytics/get-deobfuscated-reports?platform=flutter#apple-upload-dsym-script-configuration" rel="noopener noreferrer"&gt;firebase.google.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you did not use &lt;code&gt;flutterfire configure&lt;/code&gt; or did and you still get the "Missing dSYM" alert from Firebase, you will need to follow through on the steps from the &lt;a href="https://firebase.google.com/docs/crashlytics/get-deobfuscated-reports?platform=flutter#:~:text=If%20you%20have%20this%20issue%2C%20first%20make%20sure%20that%20you%20have%20the%20run%20script%20installed%3A" rel="noopener noreferrer"&gt;highlighted text downwards&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sometimes, the steps in the official documentation (previous link) don't help and sometimes cause the build process to fail depending on the complexity of your application, especially when you use the &lt;code&gt;--split-debug-info&lt;/code&gt; argument and the optional &lt;code&gt;--obfuscate&lt;/code&gt; flag.&lt;/p&gt;

&lt;p&gt;There's also the question of build schemes or flavors, concerning which Firebase credentials will be used while executing the script.&lt;/p&gt;

&lt;p&gt;If you've followed through with the links above and still not getting readable crash reports from the Firebase console, two things are certain at this point.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have an upload script present at &lt;code&gt;ios/Pods/FirebaseCrashlytics/upload-symbols&lt;/code&gt;
After a successful build process, + dSYMs are being generated at &lt;code&gt;build/ios/archive/Runner.xcarchive/dSYMs&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To upload your dSYM files, the command should be somewhat like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ios/Pods/FirebaseCrashlytics/upload-symbols &lt;span class="nt"&gt;-gsp&lt;/span&gt; &amp;lt;Absolute-Path-To-Flutter-Project-Root&amp;gt;/ios/Runner/GoogleService-Info.plist &lt;span class="nt"&gt;-p&lt;/span&gt; ios &amp;lt;Absolute-Path-To-Flutter-Project-Root&amp;gt;/build/ios/archive/Runner.xcarchive/dSYMs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The concept is the same in workflow or flavored or multi-build scheme Flutter iOS apps&lt;/p&gt;

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

&lt;p&gt;Crash reports are essential for improving and maintaining the stability of any application as they help you identify issues before they become a major disaster. Hopefully, this article will help you achieve stability in your Flutter apps.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>firebase</category>
      <category>crashlytics</category>
      <category>sentry</category>
    </item>
    <item>
      <title>A Package Manager for Code Igniter 3</title>
      <dc:creator>Francis Ilechukwu</dc:creator>
      <pubDate>Tue, 19 Mar 2019 04:35:54 +0000</pubDate>
      <link>https://forem.com/francis94c/a-package-and-dependency-manager-for-code-igniter-3-1pe5</link>
      <guid>https://forem.com/francis94c/a-package-and-dependency-manager-for-code-igniter-3-1pe5</guid>
      <description>&lt;p&gt;Code Igniter is a simple and yet powerful PHP MVC Framework. With it, one can build rich featured web applications in almost half the time required to write the same application in plain PHP while taking care of security issues at the same time.&lt;/p&gt;

&lt;p&gt;I have used Code Igniter for about 3 years to know that it’s core is really efficient and is one of the most simplest MVC framework out there.&lt;/p&gt;

&lt;p&gt;As small and simple as it is, its applications ranges from simple to very complex projects.&lt;/p&gt;

&lt;p&gt;There are only two reasons I can think of so far, that the framework has lacked over the years which prompted people to choose its alternative (Laravel) to it.&lt;/p&gt;

&lt;p&gt;The first reason is its failure to adapt to the new &lt;a href="https://www.php-fig.org/psr/psr-4" rel="noopener noreferrer"&gt;PSR-4 Auto-Loading&lt;/a&gt; feature that PHP rolled out. You’ll notice this when you try to load the same class name but in different directories as Code Igniter 3 was built to adapt to PHP 5.3.+ and has a built-in preventive mechanism to avoid clashing of class names.&lt;/p&gt;

&lt;p&gt;The code in the controller below will load only the library assigned to alias1&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nb"&gt;defined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'BASEPATH'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'No direct script access allowed'&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;MainController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;CI_Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&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="n"&gt;load&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"nodes/Lib"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"alias1"&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="n"&gt;load&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;library&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Lib"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"alias2"&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="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This problem is currently being solved by Code Igniter 4 which is currently in Beta.&lt;/p&gt;

&lt;p&gt;The second reason is, unlike Laravel, Code Igniter does not have a repository for packages that can save you a lot of development time like &lt;a href="https://packagist.org/" rel="noopener noreferrer"&gt;Packagist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;you may get libraries from GitHub but you still need to modify/copy them to the right directory in the right structure by yourself to suit Code Igniter before you can use them.&lt;/p&gt;

&lt;p&gt;Some of the libraries you may find, implement functionalities that already reside within Code Igniter, hence re-inventing the wheel. You won’t want to do this if you are the one writing a library unless it’s necessary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnk8q2mp71zh5v934r6rn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnk8q2mp71zh5v934r6rn.png" alt="Splint Logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://splint.cynobit.com" rel="noopener noreferrer"&gt;Splint&lt;/a&gt; is a Package and Dependency manager specifically built for Code Igniter to allow one build mini applications, packages that can make use of the Code Igniter Loader to load resources such as views, models, configs, libraries, etc. Whatever you can do within Code Igniter applications, you can do also within Splint packages.&lt;/p&gt;

&lt;p&gt;Loading and using a library within a Splint package is as easy as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&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="n"&gt;load&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;splint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"francis94c/ci-preference"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"+CIPreferences"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"prefs"&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="n"&gt;prefs&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the splint() function isn’t by default, a member of the loader class. However, you will need to modify the Loader class from the application/core folder. The Splint Terminal tool will do this automatically for you whenever you install a package.&lt;/p&gt;

&lt;p&gt;Splint has a &lt;a href="https://splint.cynobit.com/wiki" rel="noopener noreferrer"&gt;Wiki&lt;/a&gt; where you can learn all about how to build Splint packages. However, Splint is still very much new and has very few packages you can make use of. You can always go to their website to see the packages they have that you can install.&lt;/p&gt;

&lt;p&gt;Installing a package using the Splint Terminal tool is as easy ascan be with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;splint &lt;span class="nb"&gt;install &lt;/span&gt;vendor/package_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://splint.cynobit.com" rel="noopener noreferrer"&gt;Splint&lt;/a&gt; also has an &lt;a href="https://github.com/splintci/sdk" rel="noopener noreferrer"&gt;SDK&lt;/a&gt; which is in fact, a complete Code Igniter distribution with its loader already modified along with one platform package for use when developing/testing a package.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;All packages must be publicly hosted on GitHub before you can import them to &lt;a href="https://splint.cynobit.com" rel="noopener noreferrer"&gt;Splint&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  A Sample Splint Package
&lt;/h3&gt;

&lt;p&gt;Let’s take a look at the Splint package I built for persistence of simple key-value pairs. I call the package ci-preference and is hosted on &lt;a href="https://github.com/francis94c/ci-preference" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. You can visit it’s Splint page &lt;a href="https://splint.cynobit.com/packages/francis94c/ci-preference" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This library makes use of two main functions which are set() and get() to set values and get values by key.&lt;/p&gt;

&lt;p&gt;All you have to do to use this library in Code Igniter is to download the Splint terminal &lt;a href="https://splint.cynobit.com/downloads/splint" rel="noopener noreferrer"&gt;tool&lt;/a&gt; and run splint install francis94c/ci-preference to have the package installed within your Code Igniter distribution.&lt;/p&gt;

&lt;p&gt;Then within any controller/model, use the package as described in its README which you would find either on the Splint &lt;a href="https://splint.cynobit.com/packages/francis94c/ci-preference" rel="noopener noreferrer"&gt;page&lt;/a&gt; for the package or on it’s GitHub page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nb"&gt;defined&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'BASEPATH'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'No direct script access allowed'&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;A_Controller&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;CI_Controller&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"file_name"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"preferences"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// File name of the preference file.&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="n"&gt;load&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;splint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"francis94c/ci-preference"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"+CIPreferences"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"alias"&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="n"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"defaultVal"&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="n"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"val"&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="n"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"key1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Increments 'key1' by 5.&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="n"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"key1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// increments 'key1' by 1.&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="n"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"key2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Concatenates 'A' to 'key2'.&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="n"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Commits all values to file.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s all about it. If you have ideas about libraries you would like to build and use within Code Igniter, have a look at the Developer Docs for Splint.&lt;/p&gt;

&lt;p&gt;You can also modify other libraries/packages out there to suit Code Igniter and publish/import it to Splint as that will surely, go a long way in helping the Code Igniter community.&lt;/p&gt;

</description>
      <category>codeigniter</category>
      <category>package</category>
      <category>dependencymanagement</category>
      <category>splint</category>
    </item>
  </channel>
</rss>
