title: How to save an IP address as binary using Eloquent and PostgreSQL?
body: <p>First off, here's the SO question+answer where I got my information - <a href="https://stackoverflow.com/questions/17795517/laravel-4-saving-ip-address-to-model">laravel 4 saving ip address to model</a>.</p>
  
  <p>So my table will potentially have millions of row, therefore to keep storage low I opted for option 2 - using the Schema builder's binary() column and converting/storing IPs as binary with the help of Eloquents' accessors/mutators.</p>
  
  <p>Here's my table:</p>
  
  <pre><code>Schema::create('logs', function ( Blueprint $table ) {
      $table-&gt;increments('id');
      $table-&gt;binary('ip_address'); // postgresql reports this column as BYTEA
      $table-&gt;text('route');
      $table-&gt;text('user_agent');
      $table-&gt;timestamp('created_at');
  });
  </code></pre>
  
  <p>The first problem I ran into was saving the IP address. I set an accessor/mutator on my model to convert the IP string into binary using <code>inet_pton()</code> and <code>inet_ntop()</code>. Example:</p>
  
  <pre><code>public function getIpAddressAttribute( $ip )
  {
      return inet_ntop( $ip );
  }
  
  public function setIpAddressAttribute( $ip )
  {
      $this-&gt;attributes['ip_address'] = inet_pton( $ip );
  }
  </code></pre>
  
  <p>Trying to save an IP address resulted in the whole request failing - nginx would just return a 502 bad gateway error.</p>
  
  <p>OK. So I figured it had to be something with Eloquent/PostgreSQL not playing well together while passing the binary data.</p>
  
  <p>I did some searching and found the <code>pg_escape_bytea()</code> and <code>pg_unescape_bytea()</code> functions. I updated my model as follows:</p>
  
  <pre><code>public function getIpAddressAttribute( $ip )
  {
      return inet_ntop(pg_unescape_bytea( $ip ));
  }
  
  public function setIpAddressAttribute( $ip )
  {
      $this-&gt;attributes['ip_address'] = pg_escape_bytea(inet_pton( $ip ));
  }
  </code></pre>
  
  <p>Now, I'm able to save an IP address without a hitch (at least, it doesn't throw any errors).</p>
  
  <p>The new problem I'm experiencing is when I try to retrieve and display the IP. <code>pg_unescape_bytea()</code> fails with <code>pg_unescape_bytea() expects parameter 1 to be string, resource given</code>.</p>
  
  <p>Odd. So I <code>dd()</code> $ip in the accessor, the result is <code>resource(4, stream)</code>. Is that expected? Or is Eloquent having trouble working with the column type?</p>
  
  <p>I did some more searching and found it's possible that <code>pg_unescape_bytea()</code> is not properly unescaping the data - <a href="https://bugs.php.net/bug.php?id=45964" rel="nofollow noreferrer">https://bugs.php.net/bug.php?id=45964</a>.</p>
  
  <p>After much headbanging and hairpulling, it became apparent that I might be approaching this problem from the wrong direction, and need some fresh perspective.</p>
  
  <p>So, what am I doing wrong? Should I be using Postgres' <code>BIT VARYING</code> instead of <code>BYTEA</code> by altering the column type --</p>
  
  <pre><code>DB::statement("ALTER TABLE logs ALTER COLUMN ip_address TYPE BIT VARYING(16) USING CAST(ip_address AS BIT VARYING(16))");`
  </code></pre>
  
  <p>-- Or am I merely misusing <code>pg_escape_bytea / pg_unescape_bytea</code>?</p>
  
  <p>All help is appreciated!</p>