<?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: Ryan P</title>
    <description>The latest articles on DEV Community by Ryan P (@godsgood33).</description>
    <link>https://dev.to/godsgood33</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%2F119449%2Fb46e23cd-c27f-4896-98df-54f7cf62ff41.jpeg</url>
      <title>DEV Community: Ryan P</title>
      <link>https://dev.to/godsgood33</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/godsgood33"/>
    <language>en</language>
    <item>
      <title>CSV Reader - Links</title>
      <dc:creator>Ryan P</dc:creator>
      <pubDate>Mon, 03 Apr 2023 03:38:48 +0000</pubDate>
      <link>https://dev.to/godsgood33/csv-parser-links-4mk6</link>
      <guid>https://dev.to/godsgood33/csv-parser-links-4mk6</guid>
      <description>&lt;p&gt;In my last two posts I covered the basics of my CSV Reader and the Filter and Map functionality.  In this post, I wanted to cover the Link functionality.  Links are similar to Map.  The main difference is that Maps return a formatted string.  Links return whatever you’d like to return from the callback method.  A good example is Address data.  You have a CSV file that has customer data that includes an address.  Let’s say you want to isolate that address into it’s own Address object within the Customer object.&lt;/p&gt;

&lt;p&gt;First you create the Address object&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Address&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;…&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;fromCSV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;stdClass&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;Address&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$me&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;static&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;// you'll need to do validation on each field&lt;/span&gt;

        &lt;span class="nv"&gt;$me&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nc"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$me&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nc"&gt;City&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$me&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$me&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nc"&gt;Zip&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$me&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nc"&gt;Country&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;$me&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;Then you need to create the Link and add it to the Reader.&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;$link&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;Link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'objAddress'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Field to call that will trigger this link&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="s1"&gt;'Address'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'City'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'State'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Zip'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Country'&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// The fields as they appear in the CSV after removing invalid characters&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nc"&gt;Address&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="s1"&gt;'fromCSV'&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// The *optional* callable method to pass the data to&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$reader&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$link&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then when you call the reader and reference the &lt;code&gt;objAddress&lt;/code&gt; property it will call the method &lt;code&gt;Address::fromCSV&lt;/code&gt; and it will pass in a &lt;code&gt;stdClass&lt;/code&gt; object with each of the fields as a public property.  The callback parameter is optional and if you omit it, the return will just be that &lt;code&gt;stdClass&lt;/code&gt; object.  This can be a great option as well.&lt;/p&gt;

</description>
      <category>php</category>
      <category>csv</category>
      <category>programming</category>
    </item>
    <item>
      <title>CSV Reader - Filters and Maps</title>
      <dc:creator>Ryan P</dc:creator>
      <pubDate>Fri, 28 Oct 2022 19:00:21 +0000</pubDate>
      <link>https://dev.to/godsgood33/csv-reader-filters-and-maps-43ld</link>
      <guid>https://dev.to/godsgood33/csv-reader-filters-and-maps-43ld</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;In my previous post, &lt;a href="https://dev.to/godsgood33/csv-parsing-library-3n8o"&gt;CSV Reader&lt;/a&gt;, I discussed the CSV Reader I created.  In this post, I want to explain how the &lt;code&gt;Filters&lt;/code&gt; and &lt;code&gt;Maps&lt;/code&gt; work within the object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Filters
&lt;/h2&gt;

&lt;p&gt;Filters are a way that you filter content before ingesting it.  After creating your object you have to add the filter.&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;$filter&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;Filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nc"&gt;Phone&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;Customer&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="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;sanitizePhone&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nv"&gt;$csv&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$filter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first parameter is the field that triggers the call.  So in this case, when retrieving the Phone with &lt;code&gt;$csv-&amp;gt;Phone&lt;/code&gt;, it will call &lt;code&gt;Customer::sanitizePhone()&lt;/code&gt;.  It will automatically pass in the value from the file to that method.  So then you will need to create the method for it to call.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/**
 * Method to sanitize the phone number from a CSV file
 * @param string $val
 * @return string
 */&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;sanitizePhone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$val&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;string&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;preg_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/[^0-9\+]/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;‘’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$val&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;
  
  
  Maps
&lt;/h2&gt;

&lt;p&gt;Maps are another really powerful feature.  Maps allow you to combine multiple fields and concatenate them together into one formatted string.  One easy example is an address or a name.&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;$map&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;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nc"&gt;Address&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;\n&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="nv"&gt;$csv&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$map&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, when reading &lt;code&gt;$csv-&amp;gt;Address&lt;/code&gt; it would return with a formatted string similar to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;123 Main St
Anytown, ST  12345
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>programming</category>
      <category>php</category>
      <category>csv</category>
    </item>
    <item>
      <title>CSV Reader Library</title>
      <dc:creator>Ryan P</dc:creator>
      <pubDate>Fri, 22 Jan 2021 03:21:50 +0000</pubDate>
      <link>https://dev.to/godsgood33/csv-parsing-library-3n8o</link>
      <guid>https://dev.to/godsgood33/csv-parsing-library-3n8o</guid>
      <description>&lt;p&gt;I absolutely despise parsing CSV files because you have to know the column indexes for all the fields you want to read, but they could be in a different order for a different file.  This makes it to where you have to sanity check the file first and it's going to be different for every file you want to parse.  I did kinda find a way around it.&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;$header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_flip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;fgetcsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fh&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will create an array where the header title is an key to the column index&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;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'column1'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'column2'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'column3'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mf"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is helpful, but you still have to put something like...&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;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;fgetcsv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$fh&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$column1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$header&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'column1'&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;
&lt;span class="mf"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That is nice, but not very simple and a pain to write every time you need to parse a file.  So I did what any natural dev would do and wrote my own library that will do it all for me.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require godsgood33/csv-reader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then all you have to do is create a reader object and start parsing.&lt;/p&gt;

&lt;p&gt;So given the following file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ID | Name   | Phone Number | Email            | State
1  | Ryan   | 123-456-7890 | ryan@example.com | IN
2  | John   | 234-567-8901 | john@example.com | GA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$csv&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;Reader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$file&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;do&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$csv&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nc"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$phone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$csv&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nc"&gt;PhoneNumber&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;$email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$csv&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nc"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$csv&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The library removes any non-alphanumeric characters [A-Z, a-z, 0-9, _] from the header titles so that they are valid properties (so the space is removed from "Phone Number").  &lt;/p&gt;

&lt;p&gt;There are a couple different options you can pass in as an array when you create the object.&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="s1"&gt;'delimiter'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt; &lt;span class="c1"&gt;// character that splits the fields&lt;/span&gt;
    &lt;span class="s1"&gt;'enclosure'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt; &lt;span class="c1"&gt;// character the encloses a field should it contain the delimiter&lt;/span&gt;
    &lt;span class="s1"&gt;'header'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;// default 0-based index for what row the header is on&lt;/span&gt;
    &lt;span class="s1"&gt;'required_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="c1"&gt;// array of headers (post sanitizing) of fields you want to require are present in the file before any parsing can take place&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So if you wanted to require the ID, Name, and Email fields your object instantiation would look like:&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;$csv&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;Reader&lt;/span&gt;&lt;span class="p"&gt;(&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="s1"&gt;'required_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;'ID'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'Name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'Email'&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;Other fields would still be available for use, but are optional fields, so you'd want to validate them before using them.  If a column header is not present, it simply returns &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This library can also be used for remote files, but currently only supports http(s).  However, it would not be recommended for large remote files.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/godsgood33" rel="noopener noreferrer"&gt;
        godsgood33
      &lt;/a&gt; / &lt;a href="https://github.com/godsgood33/csv-reader" rel="noopener noreferrer"&gt;
        csv-reader
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      This library is to create a simpler way to parse CSV files.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;CSV Reader&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Intro&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;The purpose of this library is to simplify reading and parsing CSV files.  I have parsed CSV files so many times and there is not really an easy way to do it.  You have to know the index of the column you want to insert and it would be so much more readable if you could just use the header title itself as the field index.  A while ago, I started reading the header row, flipping the array so that the index of the row elements is now the value of the field index.&lt;/p&gt;

&lt;div class="highlight highlight-text-html-php notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;header&lt;/span&gt; = &lt;span class="pl-en"&gt;array_flip&lt;/span&gt;(&lt;span class="pl-en"&gt;fgetcsv&lt;/span&gt;(&lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;fh&lt;/span&gt;));
&lt;span class="pl-c"&gt;/*&lt;/span&gt;
&lt;span class="pl-c"&gt; array(&lt;/span&gt;
&lt;span class="pl-c"&gt;     'column1' =&amp;gt; 0,&lt;/span&gt;
&lt;span class="pl-c"&gt;     'column2' =&amp;gt; 1,&lt;/span&gt;
&lt;span class="pl-c"&gt;     'column3' =&amp;gt; 2,&lt;/span&gt;
&lt;span class="pl-c"&gt;     ...&lt;/span&gt;
&lt;span class="pl-c"&gt; )&lt;/span&gt;
&lt;span class="pl-c"&gt; */&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This allows you the ability to use the header title as an index into the data array.&lt;/p&gt;
&lt;div class="highlight highlight-text-html-php notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;foreach&lt;/span&gt;(&lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;data&lt;/span&gt; = &lt;span class="pl-en"&gt;fgetcsv&lt;/span&gt;(&lt;span class="pl-s1"&gt;&lt;span class="pl-c1"&gt;$&lt;/span&gt;fh&lt;/span&gt;)) {
  &lt;span class="pl-c"&gt;//&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/godsgood33/csv-reader" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>php</category>
      <category>csv</category>
    </item>
    <item>
      <title>PHP MySQL Library Pt3</title>
      <dc:creator>Ryan P</dc:creator>
      <pubDate>Mon, 15 Jul 2019 04:08:45 +0000</pubDate>
      <link>https://dev.to/godsgood33/php-mysql-library-pt3-4bj1</link>
      <guid>https://dev.to/godsgood33/php-mysql-library-pt3-4bj1</guid>
      <description>&lt;p&gt;In part 1 of this series, I talked about this Php_Db library that I created.  In part 2 I showed a good number of the function and queries that you can create using it.  In this part, I'm going to talk about the DDL queries that you can create with Php_Db&lt;/p&gt;

&lt;h2&gt;
  
  
  drop
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;returns mysqli_result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The drop function will create a drop statement that allows you to drop a table or view from your schema.  By default it will pull drop a table&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$this-&amp;gt;drop('users')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;DROP TABLE users&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$this-&amp;gt;drop('user_view', 'view')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;DROP VIEW user_view&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There is also a third parameter that allows you to specify that the table is a temporary table.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$this-&amp;gt;drop('tmp_user', 'table', true)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;DROP TEMPORARY TABLE tmp_user&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  truncate
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;returns mysqli_result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The truncate function allows you to create a truncate table statement to delete all records from a table&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$this-&amp;gt;truncate('users')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;TRUNCATE TABLE users&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  createTable
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;returns mysqli_result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The createTable function allows you to create a table or temporary table either using an array or select statement (this can also use an existing saved select statement).  The second parameter is weather this table will be a temporary table.  The third parameter defines what fields will be created in this table.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$this-&amp;gt;createTable('new_users', false, [
    [
        'field' =&amp;gt; 'id',
        'datatype' =&amp;gt; 'int(11)',
        'option' =&amp;gt; 'AUTO_INCREMENT PRIMARY KEY'
    ],
    [
        'field' =&amp;gt; 'name',
        'datatype' =&amp;gt; 'varchar(255)',
        'default' =&amp;gt; null
    ],
    [
        'field' =&amp;gt; 'email',
        'datatype' =&amp;gt; 'varchar(64)',
        'default' =&amp;gt; null
    ]
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;CREATE TABLE IF NOT EXISTS new_users (&lt;br&gt;
    id int(11) AUTO_INCREMENT PRIMARY KEY,&lt;br&gt;
    name varchar(255),&lt;br&gt;
    email varchar(255)&lt;br&gt;
);&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As I said above, you can also use a select query.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$this-&amp;gt;createTable('new_users', false, "SELECT * FROM users");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;CREATE TABLE IF NOT EXISTS new_users AS (SELECT * FROM users);&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  createTableJson
&lt;/h2&gt;

&lt;p&gt;createTableJson allows you to pass a pre-formatted JSON string which will make the create table string.  There is an example of the json file format in /vendor/godsgood33/php-db/examples/&lt;/p&gt;

&lt;h2&gt;
  
  
  alterTable
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;returns mysqli_result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The alterTable function allows you to create a statement to alter a database table by adding, dropping, or modifying a column.  alterTable does this by having 3 parameters, the table to edit, the action to take (ADD_COLUMN, DROP_COLUMN, MODIFY_COLUMN, &amp;amp; ADD_CONSTRAINT), and the parameters.  The actions are constants in the Database class.&lt;/p&gt;

&lt;h3&gt;
  
  
  ADD_COLUMN:
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$phoneColumn = new stdClass();
$phoneColumn-&amp;gt;name = 'phone';
$phoneColumn-&amp;gt;dataType = 'varchar(20)';
$phoneColumn-&amp;gt;default = null;

$this-&amp;gt;alterTable('users', \Godsgood33\Php_Db\Database::ADD_COLUMN, [
    $phoneColumn
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;ALTER TABLE users ADD COLUMN phone varchar(20) DEFAULT NULL&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  DROP_COLUMN:
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$phoneColumn = new stdClass();
$phoneColumn-&amp;gt;name = 'phone';

$this-&amp;gt;alterTable('users', \Godsgood33\Php_Db\Database::DROP_COLUMN, [
    $phoneColumn
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;ALTER TABLE users DROP COLUMN phone&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  MODIFY_COLUMN:
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$emailColumn = new stdClass();
$emailColumn-&amp;gt;name = 'email';
$emailColumn-&amp;gt;new_name = 'user_email';
$emailColumn-&amp;gt;dataType = 'varchar(255)';
$emailColumn-&amp;gt;default = null;

$this-&amp;gt;alterTable('users', \Godsgood33\Php_Db\Database::MODIFY_COLUMN, [
    $emailColumn
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;ALTER TABLE users MODIFY COLUMN email user_email varchar(255) DEFAULT NULL&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ADD_CONSTRAINT:
&lt;/h3&gt;

&lt;h2&gt;
  
  
  setVar
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NULL return
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Allows you to set a SQL variable&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$this-&amp;gt;setVar('foo', 'bar');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  tableExists
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;returns boolean
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Check to see if a table exists&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$this-&amp;gt;tableExists('schema', 'table');&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  fieldExists&lt;br&gt;
&lt;/h2&gt;

</description>
      <category>php</category>
      <category>mysql</category>
      <category>wordpress</category>
    </item>
    <item>
      <title>PHP MySQLi Library Pt2</title>
      <dc:creator>Ryan P</dc:creator>
      <pubDate>Mon, 15 Jul 2019 04:08:21 +0000</pubDate>
      <link>https://dev.to/godsgood33/php-mysqli-library-pt2-1ip1</link>
      <guid>https://dev.to/godsgood33/php-mysqli-library-pt2-1ip1</guid>
      <description>&lt;p&gt;In my previous post &lt;a href="https://dev.to/godsgood33/php-mysqli-library-pt1-5778"&gt;Part 1&lt;/a&gt;, I talked about the basics of the PHP MySQL library that I wrote.  In this post, I'm going to talk about the different queries you can run.  I am going to assume that you are operating within your own database class that you extended with Php_Db.&lt;/p&gt;

&lt;p&gt;A couple notes.  By default, function calls will return the SQL that was built from the parameters that were passed in.  If you change the &lt;code&gt;$autorun&lt;/code&gt; static variable to &lt;code&gt;true&lt;/code&gt;, it will automatically execute any calls and return the result of the query.  So you would want to store the return in a variable or check it against an &lt;code&gt;if()&lt;/code&gt; block.  If &lt;code&gt;$autorun&lt;/code&gt; remains &lt;code&gt;false&lt;/code&gt; it returns the string SQL, but it also stores it (until another function is called).  If you want to run it, call &lt;code&gt;$this-&amp;gt;execute()&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  select
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Returns
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`stdClass` or `array:stdClass`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Definition
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;select($strTableName, $fieldList = [], $whereClauses = [], $flags = [])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So a select statement obviously is what most people do.  Just like the previous post showed, you need one parameter, with 3 more being optional.  So a call to &lt;code&gt;$this-&amp;gt;select("users");&lt;/code&gt; will pull ALL fields and ALL records from the table &lt;code&gt;users&lt;/code&gt;.  If you only want to pull the id and name fields for example, you would run &lt;code&gt;$this-&amp;gt;select("users", ['id', 'name']);&lt;/code&gt;  Again, this would return the id and name fields for ALL records.  So now, the real power!  You want to pull a specific list of all users with the name containing 'George'.  That would look like...&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$where = new DBWhere('name', '%George%', DBWhere::LIKE);
// You have to set escape equal to false so that it doesn't escape the wildcards
$where-&amp;gt;escape = false;

$this-&amp;gt;select("users", ['id', 'name'], $where);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;SELECT 'id', 'name' FROM users WHERE name LIKE '%George%'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Again, this can be expanded or refined further with the 'flags' parameter.&lt;/p&gt;

&lt;h2&gt;
  
  
  selectCount
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Definition
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;selectCount($strTableName, $whereClauses, $flags)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Returns
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;number
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;A selectCount query will just return the number of rows that satisfy the WHERE clause.  The big different is that there is no 'field list' in this call.  To return the number of all users whose names contain the string 'George' you would call...&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$where = new DBWhere('name', '%George%', DBWhere::LIKE);
$where-&amp;gt;escape = false;

$this-&amp;gt;selectCount("users", $where);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;SELECT COUNT(1) FROM users WHERE name LIKE '%George%'&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  insert
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Definition
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;insert($strTableName, $params, $blnIgnore = false)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Returns
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;number of affected rows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The insert query will create a single insert statement that allows you to insert a single row to a table.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$this-&amp;gt;insert("users", [
    'id' =&amp;gt; 1,
    'name' =&amp;gt; 'George Jetson',
    'email' =&amp;gt; 'george.jetson@spacelysprockets.com'
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;INSERT INTO users ('id', 'name', 'email') VALUES ('1', 'George Jetson', 'george.jetson@spacelysprockets.com')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This also stores the insert id from the previous query, so you can retrieve it by accessing &lt;code&gt;$this-&amp;gt;_insertId&lt;/code&gt;  Optionally, you can also specify a third boolean parameter if you want to add an "IGNORE" clause to the query&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INSERT IGNORE INTO...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  extendedInsert
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Definition
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;extendedInsert($strTableName, $arrFields, $params, $blnToIgnore = false)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Returns
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;number of affected rows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This query will create a multi-insert statement that allows you to insert multiple rows at a time.  This query is a little different in that it requires the addition of the field list for the second parameter and an array of arrays with the list of items to put in each field.  The order must be the same!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$this-&amp;gt;extendedInsert("users", ['id', 'name', 'email'], [
    ['1', 'George Jetson', 'george.jetson@spacelysprockets.com'],
    ['2', 'Fred Flintsone', null]
], true);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;INSERT IGNORE INTO users ('id', 'name', 'email') VALUES&lt;br&gt;
('1', 'George Jetson', 'george.jetson@spacelysprockets.com'),&lt;br&gt;
('2', 'Fred Flintstone', NULL)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; As you see if &lt;code&gt;null&lt;/code&gt; is the value of a field in most cases it will translate to &lt;code&gt;NULL&lt;/code&gt; in MySQL.&lt;/p&gt;

&lt;h2&gt;
  
  
  update
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Definition
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;update($strTableName, $params, $whereClauses = [], $flags = [])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Returns
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;number of affected rows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This query will create an update query.  This is very similar to an insert query, but the 3rd parameter is a where clause.  You can also use the flags to effect change in joined tables.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$this-&amp;gt;update("users", ['email' =&amp;gt; null], new DBWhere('id', 1));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;UPDATE users SET email = NULL WHERE id = 1&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  extendedUpdate
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Definition
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;extendedUpdate($strTableToUpdate, $strOriginalTable, $strLinkField, $fieldsToUpdate)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Returns
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;number of affected rows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The extended update query creates an update query that updates one table using another.  So the best option is to create a TEMPORARY table that you insert updated data in.  Then using this query to update permanent table data with the data from the temporary table.&lt;/p&gt;

&lt;p&gt;The first parameter is the table to update.  The second parameter is the source table for the update.  The third parameter is the field that is common between the two table and used as the to decide what records to update.  The fourth parameter can either be a string or array and is a list or particular field you want updated.  So in this case only the name and email fields will be updated.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$this-&amp;gt;extendedUpdate('users', 'tmp_users', 'id', ['name', 'email']);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;UPDATE users tbu INNER JOIN tmp_users o USING ('id') SET tbu.name = o.name, tbu.email = o.email&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  replace
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Definition
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;replace($strTableName, $params)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Returns
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;number of affected rows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The replace function is built exactly like the insert function, except as a replace function which runs a &lt;code&gt;delete&lt;/code&gt; statement first, then an &lt;code&gt;insert&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  extendedReplace
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Definition
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;extendedReplace($strTableName, $fieldList, $param)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Returns
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;number of affected rows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The extendedReplace function is built exactly like the extendedInsert function&lt;/p&gt;

&lt;h2&gt;
  
  
  delete
&lt;/h2&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;returns number of affected rows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The delete function creates a delete query to remove records from the table.  The second parameter is an array list of fields you want to remove.  This is provided so that you can remove rows from a specific table and not a joined table&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// true and false will automatically be converted to '1' and '0', respectfully
$where = new DBWhere('um.active', false);
// the backticks parameter must be set to false to not surround the field with backticks
// e.g. `um.active`, which is not valid
$where-&amp;gt;backticks = false;

$this-&amp;gt;delete('users u', ['u.*'], $where, [
    'joins' =&amp;gt; [
        "JOIN user_meta um ON um.user_id = u.id"
   ]
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;DELETE u.* FROM users u JOIN user_meta um ON um.user_id = u.id WHERE um.active = '0'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This covers most of the main queries that Php_Db can run.  There are a few other DDL queries that it can also build, but I will go into those in the next part.&lt;/p&gt;

</description>
      <category>php</category>
      <category>mysql</category>
      <category>wordpress</category>
    </item>
    <item>
      <title>PHP MySQLi Library Pt1</title>
      <dc:creator>Ryan P</dc:creator>
      <pubDate>Tue, 02 Jul 2019 14:33:17 +0000</pubDate>
      <link>https://dev.to/godsgood33/php-mysqli-library-pt1-5778</link>
      <guid>https://dev.to/godsgood33/php-mysqli-library-pt1-5778</guid>
      <description>&lt;p&gt;I really love the way that the WordPress WPDB class works.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$wpdb-&amp;gt;insert('table', ['field' =&amp;gt; 'value']);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Done!&lt;/p&gt;

&lt;p&gt;It does the statement creation and automatic escaping 'problematic' characters.  But there's not an easy way to add it to your project.  There are other variables like "posts", that contains the table name for the posts table, that are unnecessary for most.  So I decided to create &lt;a href="https://github.com/godsgood33/php-db" rel="noopener noreferrer"&gt;Php_Db&lt;/a&gt; that does most all the same things.  I thought about using the library ezSQL that WPDB is based on, but it didn't include some very fundamental things that I wanted an extended insert, replace, and update functionality, along with some DDL capabilities.  There were other things, but I saw a big need for those. &lt;br&gt;
I'm going to take a couple days to talk about how Php_Db works because I put a lot of functionality in it.  For full documentation you can look at my &lt;a href="https://php-db.readthedocs.io/en/stable/" rel="noopener noreferrer"&gt;Docs&lt;/a&gt; or &lt;a href="https://github.com/godsgood33/php-db" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So installation...&lt;br&gt;
&lt;code&gt;composer require godsgood33/php_db&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now you need to run the setup to generate some defined variables.  Navigate to {project_dir}/vendor/godsgood33/php_db.  Now if you would like to encrypt your DB password that Php_Db uses, run &lt;code&gt;php bin/setup.php --algorithms&lt;/code&gt; to display the list of all your systems supported OpenSSL algorithms.  Once you decide on one, rerun &lt;code&gt;php bin/setup.php -a={algorithm}&lt;/code&gt;  If you don't want to encrypt the password you can just run &lt;code&gt;php bin/setup.php&lt;/code&gt; for the same questions.&lt;/p&gt;

&lt;p&gt;It will then ask you a couple questions, MySQL server name/IP, user name, password, and schema.  Then it prints out a list of constants you need to add to your project.  Once you include those you can start using Php_Db.  The best place to put them is in your bootstrap or index file.  Just as long as it is done prior to instantiating your db class.&lt;/p&gt;

&lt;p&gt;If you ever change your username or password, or you want to change your encryption algorithm, you can just rerun setup.php to get the new values, update your constants, and you're good.  &lt;strong&gt;WARNING&lt;/strong&gt; If you use Php_Db to encrypt any data you insert into your database you are going to have to decrypt it first, then change your algorithm, then you can re-encrypt it.  Which all you have to do is call the &lt;code&gt;encrypt&lt;/code&gt; / &lt;code&gt;decrypt&lt;/code&gt; methods at the appropriate times.&lt;/p&gt;

&lt;p&gt;I recommend using Php_Db to extended your database class&lt;br&gt;
&lt;code&gt;class db extends \Godsgood33\Php_Db\Database {}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So now, some basic functionality.&lt;/p&gt;

&lt;p&gt;The field list, WHERE clauses, and "flags" all operate the same independent of which query you are running (select, insert, delete...)&lt;/p&gt;

&lt;p&gt;Just like WPDB the first parameter in a query is the table name.  This is just a string that you can put single or multiple tables and/or add aliases if you like.  It just needs to look like it would if you were writing the SQL query itself.&lt;br&gt;
&lt;code&gt;"table"&lt;/code&gt; OR &lt;code&gt;"table1 t1, table2 t2"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The next parameter in is the field list.  This is simply an array of fields you want to ingest in your results.  Again, just like the SQL query.&lt;br&gt;
&lt;code&gt;['id', 'name']&lt;/code&gt; OR &lt;code&gt;['t1.id', 't2.name']&lt;/code&gt; &lt;strong&gt;NOTE&lt;/strong&gt;: There is no field list parameter in the &lt;code&gt;selectCount&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;The third parameter is the WHERE clause list.  This is an array of \Godsgood33\Php_Db\DBWhere objects.&lt;/p&gt;

&lt;p&gt;DEFINITION:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$where = new DBWhere($field = null, $value = null, $operator = '=')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So let's say you wanted to find a user with a specific ID&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$where = new DBWhere('id', 1234);
$this-&amp;gt;select('users', null, $where);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This query would look like &lt;code&gt;SELECT * FROM users WHERE id = '1234'&lt;/code&gt;.  So what do you do when you want to provide multiple where clauses?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$where1 = new DBWhere('fname', 'Fred');
$where2 = new DBWhere('lname', 'Flintstone');
$this-&amp;gt;select('users', null, [$where1, $where2]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;SELECT * FROM users WHERE fname = 'Fred' AND lname = 'Flintstone'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;By default, DBWhere will use a 'AND' operator between the clauses.  You can use any other SQL supported operator by updating the &lt;code&gt;DBWhere::$sqlOperator&lt;/code&gt; property.  So that could turn into...&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$where1 = new DBWhere('lname', 'Flintstone');
$where2 = new DBWhere('lname', 'Jetson');
$where2-&amp;gt;sqlOperator = 'OR';
$this-&amp;gt;select('users', null, [$where1, $where2]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;SELECT * FROM users WHERE lname = 'Flintstone' OR lname = 'Jetson'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you want to look for multiple values and use an IN operator you can call&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$where = new DBWhere('id', [1,2,3], DBWhere::IN)
$this-&amp;gt;select('users', null, $where);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;SELECT * FROM users WHERE id IN ('1','2','3')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can also use &lt;code&gt;NOT_IN&lt;/code&gt;, &lt;code&gt;BETWEEN&lt;/code&gt;, &lt;code&gt;LIKE&lt;/code&gt;, &lt;code&gt;NOT_LIKE&lt;/code&gt;, &lt;code&gt;IS&lt;/code&gt;, or &lt;code&gt;IS_NOT&lt;/code&gt;. &lt;br&gt;
 You can also use normal operators &lt;code&gt;=&lt;/code&gt;, &lt;code&gt;!=&lt;/code&gt;, &lt;code&gt;&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt;, &lt;code&gt;&amp;gt;=&lt;/code&gt;.  If 'operator' parameter is not specified it uses '=' as the default operator.&lt;/p&gt;

&lt;p&gt;DBWhere also does automatic conversion and escaping for the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;null&lt;/code&gt; = NULL&lt;/li&gt;
&lt;li&gt;DateTime = 'Y-m-d H:i:s'&lt;/li&gt;
&lt;li&gt;boolean = '0' or '1'&lt;/li&gt;
&lt;li&gt;array = each element is escaped&lt;/li&gt;
&lt;li&gt;objects = if the object has a callable '_escape' method, it will call that and return the result&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lastly, there are flags, &lt;code&gt;join&lt;/code&gt;, &lt;code&gt;having&lt;/code&gt;, &lt;code&gt;order&lt;/code&gt;, &lt;code&gt;group&lt;/code&gt;, and &lt;code&gt;limit&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;join&lt;/code&gt; = The join key is an array of join strings&lt;br&gt;
&lt;code&gt;having&lt;/code&gt; = The having key is an array of DBWhere object just like the WHERE clauses&lt;br&gt;
&lt;code&gt;order&lt;/code&gt; = Can either be a string or an array list of ordering clauses&lt;br&gt;
&lt;code&gt;group&lt;/code&gt; = Can be a string or array just like &lt;code&gt;order&lt;/code&gt;&lt;br&gt;
&lt;code&gt;limit&lt;/code&gt; = A string with the number you want to limit (can include the starting row)&lt;/p&gt;

&lt;p&gt;So a potential flags array could look like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
    'joins' =&amp;gt; [
        'JOIN table2 t2 ON t2.id = t1.id',
        'JOIN table3 t3 ON t3.id = t2.id'
    ],
    'having' =&amp;gt; [
        new DBWhere('age', 18, '&amp;gt;=')
    ],
    'order' =&amp;gt; 't1.name DESC',
    'group' =&amp;gt; 't1.id',
    'limit' =&amp;gt; '10'
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Again, these are the main parameters that are allowed for most of the query types.  I am going to go in more detail about the different queries themselves in the next post.  And as always there is more detail in the &lt;a href="https://php-db.readthedocs.io/en/stable/" rel="noopener noreferrer"&gt;full docs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>mysql</category>
      <category>wordpress</category>
      <category>wpdb</category>
    </item>
    <item>
      <title>Mobile streaming with a Raspberry Pi 3</title>
      <dc:creator>Ryan P</dc:creator>
      <pubDate>Mon, 24 Jun 2019 01:58:56 +0000</pubDate>
      <link>https://dev.to/godsgood33/mobile-streaming-with-a-raspberry-pi-3-3bcj</link>
      <guid>https://dev.to/godsgood33/mobile-streaming-with-a-raspberry-pi-3-3bcj</guid>
      <description>&lt;p&gt;I have 8 children (soon to be 9).  Yes, I know what causes it (and I'm good at it)!  I used to have a Ford E-350 that had an overhead DVD player.  So when we would go on family trips we would just take an assortment of DVD's to play on it.  That van is no longer with us, so I wanted another solution that didn't involve having to take a bunch of DVD's with us.&lt;/p&gt;

&lt;p&gt;Then I had a great idea!  I had a PlexPass membership and a couple extra Raspberry Pi's (model 3).  A quick Google search later and I found &lt;a href="https://github.com/billz/raspap-webgui" rel="noopener noreferrer"&gt;RaspAP-WebGUI &lt;/a&gt; and I was off to the races!&lt;/p&gt;

&lt;p&gt;After much consternation though, I determined there was a compatibility issue between Plex and RaspAP.  I ended up putting it away while I thought about what else I could do.&lt;/p&gt;

&lt;p&gt;After a couple of months, I realized all I needed was a DLNA server.  So another Google search later and I found these instructions for &lt;a href="https://www.instructables.com/id/Raspberry-Pi-Media-Server-MiniDLNA/" rel="noopener noreferrer"&gt;MiniDLNA&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Armed with all this new knowledge I set off, again.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install Raspbian&lt;/li&gt;
&lt;li&gt;Install &lt;a href="https://github.com/billz/raspap-webgui" rel="noopener noreferrer"&gt;RaspAP-WebGUI&lt;/a&gt; per README&lt;/li&gt;
&lt;li&gt;Install &lt;a href="https://www.instructables.com/id/Raspberry-Pi-Media-Server-MiniDLNA/" rel="noopener noreferrer"&gt;MiniDLNA&lt;/a&gt; per link&lt;/li&gt;
&lt;li&gt;Optimize and copy media&lt;/li&gt;
&lt;li&gt;Install VLC and Enjoy!!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first three are pretty self-explanatory, a couple notes though.  When the Pi is booting the MiniDLNA service starts BEFORE my external media is mounted.  This leads to it not finding the media.  I changed &lt;code&gt;/etc/init.d/minidlna&lt;/code&gt; and added a &lt;code&gt;sleep 10&lt;/code&gt; near the top of the script to give the Pi some time to mount the drive, before the service started, then once it did start it would find the media on the drive.  If you have problems you can just restart the minidlna service (so make sure you setup SSH Server on the Pi and have an SSH client on your device ie. JuiceSSH).  #2 I also had problems with it finding the media because of the permissions required.  You may need to tweak the permissions that the MiniDLNA service runs with (I changed the user to root, I know, not secure, but it worked).&lt;/p&gt;

&lt;p&gt;So with the 4th step, I used my Plex server to optimize a selection of MY LEGALLY OBTAINED movies (Optimize for Mobile) for my kids and then copied them to an NVMe SSD in an external USB-C enclosure.  This helps a couple of different ways. 1. It makes it easier on the Pi so it doesn't have to transcode. 2. It shrinks the files so you can fit more on it.&lt;/p&gt;

&lt;p&gt;For the last step, you'll connect your mobile devices to the new RaspAP network that you setup.  Then using VLC (search your app store), you can go to "Stream" and enter &lt;code&gt;upnp://http://10.3.141.1:8200&lt;/code&gt; (provided you kept the defaults for RaspAP.  You will see a couple files go past as it's reading the external media, but then you can select the "Playlist" from the top right of the screen and select any file on the external drive.  On the iPad, you can select "Network Stream" and it will find the UPNP MiniDLNA server and then you can just navigate through that for your list.&lt;/p&gt;

&lt;p&gt;In my testing, I was able to get 6 Kindles, 2 phones, and 1 iPad, all streaming at the same time!  No drops, no hick-ups, perfect streaming!  I did have another iPad I tried to connect, but it wasn't reliable. So it seemed that 9 is the upper capacity for the WiFi.  It might do more if I purchased an AC router and direct connected the Pi to that. &lt;/p&gt;

&lt;p&gt;Comment if you'd like me to do a video on how to set it up!&lt;/p&gt;

</description>
      <category>raspi</category>
      <category>mobile</category>
      <category>media</category>
      <category>dlna</category>
    </item>
  </channel>
</rss>
