<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Analog Lifestyle OutLoud]]></title><description><![CDATA[The more you explain it, the more I don't understand it. -Mark Twain]]></description><link>http://blog.analoglifestyle.com/</link><generator>Ghost 0.11</generator><lastBuildDate>Tue, 10 Sep 2024 01:56:41 GMT</lastBuildDate><atom:link href="http://blog.analoglifestyle.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Get an Attribute (Multi)Select's Option ID in Magento 2]]></title><description><![CDATA[As a result of the EAV data structure in Magento, the options of a select or multiselect attribute are stored and retrieved by id.]]></description><link>http://blog.analoglifestyle.com/get-an-attribute-option-id-in-magento-2/</link><guid isPermaLink="false">edc63868-53ec-4696-8f90-c031d03dc675</guid><category><![CDATA[Magento2]]></category><dc:creator><![CDATA[Kevin DeBernardi]]></dc:creator><pubDate>Wed, 09 Nov 2016 19:18:13 GMT</pubDate><media:content url="http://blog.analoglifestyle.com/content/images/2016/11/photo-1442124920820-8e5f4b07b563.jpeg" medium="image"/><content:encoded><![CDATA[<img src="http://blog.analoglifestyle.com/content/images/2016/11/photo-1442124920820-8e5f4b07b563.jpeg" alt="Get an Attribute (Multi)Select's Option ID in Magento 2"><p>As a result of the EAV data structure in Magento, the options of a <code>select</code> or <code>multiselect</code> attribute are stored and retrieved by <code>id</code>. This poses a challenge when getting the attribute in that calling <code>getAttName()</code> or <code>getData('att_name')</code> on an object (product, customer, etc.) will return the <code>id</code> instead of the text value that may be expected. This is easily addressed by Magento with the method <code>getAttributeText('att_name')</code> which will return the text string.</p>

<p><strong>Note:</strong> <em>In the methods mentioned above "AttName" and "att_name" would be replaced by the attribute name. For instance, a "Button Count" attribute would be retrieved with</em> <code>getButtonCount()</code> <em>or</em> <code>getData('button_count')</code><em>.</em></p>

<p>On the other side, there are times on the backend when you may need to find the attribute's value id from it's text, for instance to store or add it to a new product. This takes a bit more effort, but is still relatively easy. You will need to inject <code>Magento\Eav\Api\AttributeRepositoryInterface</code> into your class. A minimal example using our "Button Count" attribute would be:</p>

<pre><code>class Example
{
    /**
     * Attribute repository
     * 
     * @var \Magento\Eav\Model\AttributeRepository
     */
    protected $attributeRepository;

    public function __construct(
        \Magento\Eav\Api\AttributeRepositoryInterface $attributeRepository
    ) {
        $this-&gt;attributeRepository = $attributeRepository;
    }

    public function getButtonCountOptionId()
    {
        $attribute = $this-&gt;attributeRepository-&gt;get('catalog_product', 'button_count');
        return $attribute-&gt;getSource()-&gt;getOptionId('Three Buttons');
    }
}
</code></pre>

<p>Our <code>getButtonCountOptionId()</code> method would return a <code>string</code> containing the ID associated with the "Three Buttons" select option, such as <code>'234'</code>.</p>

<p><strong>Note:</strong> <em>When we inject and instantiate the interface</em> <code>Magento\Eav\Api\AttributeRepositoryInterface</code> <em>we will get an object with the class</em> <code>Magento\Eav\Model\AttributeRepository</code><em>. This is due to the preference set by the Magento Eav module in</em> <code>Magento\Eav\etc\di.xml</code><em>.</em></p>

<p><strong>Referenced Files</strong> <br>
<a href="https://github.com/magento/magento2/blob/develop/app/code/Magento/Eav/Api/AttributeRepositoryInterface.php">Magento\Eav\Api\AttributeRepositoryInterface</a> <br>
<a href="https://github.com/magento/magento2/blob/develop/app/code/Magento/Eav/Model/AttributeRepository.php">Magento\Eav\Model\AttributeRepository</a> <br>
<a href="https://github.com/magento/magento2/blob/develop/app/code/Magento/Eav/etc/di.xml">Magento\Eav\etc\di.xml</a></p>

<p><em>Photo by <a href="https://unsplash.com/photos/XtXdHH-Ib7c">Olia Gozha</a> at <a href="https://unsplash.com/">Unsplash</a></em></p>]]></content:encoded></item><item><title><![CDATA[Simple, Modern LEMP Using Vagrant]]></title><description><![CDATA[Vagrant is indispensable for quickly spinning up a local environment. When used with VirtualBox, it provides cheap, easy, disposable servers.]]></description><link>http://blog.analoglifestyle.com/simple-modern-lemp-using-vagrant/</link><guid isPermaLink="false">c9d6e94a-064d-46a7-b6ca-ca108e07e09b</guid><category><![CDATA[vagrant]]></category><category><![CDATA[php7]]></category><category><![CDATA[mysql]]></category><category><![CDATA[nginx]]></category><category><![CDATA[virtualbox]]></category><dc:creator><![CDATA[Kevin DeBernardi]]></dc:creator><pubDate>Sat, 05 Mar 2016 02:11:27 GMT</pubDate><media:content url="http://blog.analoglifestyle.com/content/images/2016/03/photo-1447877085163-3cce903855cd.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://blog.analoglifestyle.com/content/images/2016/03/photo-1447877085163-3cce903855cd.jpg" alt="Simple, Modern LEMP Using Vagrant"><p><a href="https://www.vagrantup.com/" title="Vagrant">Vagrant</a> is an indispensable part of my development tool belt for quickly spinning up a local environment on Mac OS X. When used with <a href="https://www.virtualbox.org/" title="VirtualBox">VirtualBox</a>, it provides cheap, easy, disposable servers that alleviate any fears of breaking something or catastrophic loss.</p>

<p>At it's heart Vagrant is simple to configure and run, but can become increasingly overwhelming as your needs grow more and more complex. While provisioning tools such as <a href="https://www.chef.io/" title="Chef">Chef</a>, <a href="https://puppetlabs.com/" title="Puppet">Puppet</a>, <a href="http://saltstack.com/" title="SaltStack">SaltStack</a>, and <a href="https://www.ansible.com/" title="Ansible">Ansible</a> help with complexity, they aren't necessary for, and at times hinder, "quick and easy" setups. We will ignore them here.</p>

<p>Let's create a simple, modern LEMP stack utilizing the following components:</p>

<ul>
<li>Ubuntu 14.04</li>
<li>Nginx 1.8.x</li>
<li>MySQL 5.7</li>
<li>PHP7</li>
</ul>

<p>We will build the server via the command line in order to remove any cruft between ourselves and the machine, facilitating a more innate understanding of the process.</p>

<p><strong>Note:</strong> <em>These instructions are purposefully limited in scope to support ease of use, ignoring most configuration, security, and best-practices commonly utilized on a production server. This is fast and loose.</em></p>

<h6 id="vagrantandubuntu1404">Vagrant and Ubuntu 14.04</h6>

<p>Let's begin by installing Vagrant onto the machine we are working from. Visit the <a href="https://www.vagrantup.com/downloads.html" title="Download Vagrant">downloads page</a> and perform the installation.</p>

<p>Additionally, Vagrant uses a <em>provider</em> which performs the actual <em>virtualization</em> of the environment. Two common providers are VirtualBox and VMWare. We will use VirtualBox for the reason that it is free. Visit <a href="https://www.virtualbox.org/" title="Download VirtualBox">this page</a>, download the software, and perform the installation.</p>

<p>With Vagrant and VirtualBox successfully installed it's time to move forward. Let's create a directory to hold the required files. Open your console of choice and run the following commands:</p>

<pre><code>$ cd ~/Documents
$ mkdir MyVagrant &amp;&amp; cd MyVagrant
$ mkdir html
</code></pre>

<p><strong>Note:</strong> <em>The final command above creates a <code>MyVagrant/html</code> directory which will be used later. You can ignore it for the moment.</em></p>

<p>Now, with a few more simple commands, we can immediately build and start a virtual Ubuntu 14.04 machine.</p>

<p><strong>Note:</strong> <em>You will be downloading a <a href="https://www.vagrantup.com/docs/getting-started/boxes.html" title="Vagrant Boxes">base box</a> for the first time, which may take a while to complete. Boxes only need to be downloaded once, and can then be reused on many virtual machines.</em></p>

<pre><code>$ vagrant init ubuntu/trusty64
$ vagrant up
</code></pre>

<p>Once <code>vagrant up</code> is executed, your virtual machine is using space and resources on your computer. At any time you can remove the virtual machine by running <code>vagrant destroy</code> and free up the used space and resources. Need the machine back? Simply run <code>vagrant up</code> again.</p>

<p><strong>Note:</strong> <em>For a full list of <code>vagrant</code> commands, visit <a href="https://www.vagrantup.com/docs/cli/" title="Vagrant Command-Line Interface">this page</a>.</em></p>

<p>At this point, you can execute <code>vagrant ssh</code> and you will be automatically SSH'd into the virtual machine. Go ahead and explore. Once you are done looking aound, simply <code>logout</code>.</p>

<p>As noted in the console, <code>vagrant init</code> created a <code>Vagrantfile</code>. This file holds the instructions used to build the base environment. Using your text editor of choice, take a moment to investigate the <code>Vagrantfile</code> and it's configuration options.</p>

<p><strong>Note:</strong> <em>You can create as many <code>Vagrantfile</code>s as you want, provided they are in different locations, but be aware that any <code>vagrant ...</code> commands must be executed in the directory containing the <code>Vagrantfile</code> you want to reference. In our case, since we are in the <code>MyVagrant</code> directory, the <code>vagrant ...</code> commands are using that <code>Vagrantfile</code>.</em></p>

<p>Let's make and implement a few changes to our current <code>Vagrantfile</code>. Using your text editor, find the following line:</p>

<pre><code># config.vm.network "private_network", ip: "192.168.33.10"
</code></pre>

<p>And uncomment it:</p>

<pre><code>config.vm.network "private_network", ip: "192.168.33.10"  
</code></pre>

<p>Then find the line:</p>

<pre><code># config.vm.synced_folder "../data", "/vagrant_data"
</code></pre>

<p>Uncomment <em>and</em> edit it to read:</p>

<pre><code>config.vm.synced_folder "html", "/var/www/html"  
</code></pre>

<p><strong>Note:</strong> <em>Both edits to the <code>Vagrantfile</code> above will come in to play shortly when we introduce Nginx, but recognize that the first argument of <code>config.vm.synced_folder</code> is in reference to the <code>html</code> directory we created earlier.</em></p>

<p>With those changes made, save the modified <code>Vagrantfile</code> and execute <code>vagrant reload</code> on the command-line. This will implement our edits and restart the virtual machine.</p>

<h6 id="nginx18x">Nginx 1.8.x</h6>

<p>With our virtual machine up and running, let's install our first component, <a href="http://nginx.org/" title="Nginx">Nginx</a>. Begin by logging in to the machine using <code>vagrant ssh</code>.</p>

<p>Let's use the most recent <em>stable</em> version of Nginx and since the default Ubuntu repository has a slightly out-of-date version, we need to start by adding an additional repository. To do so, execute the following commands:</p>

<pre><code>$ sudo add-apt-repository -y ppa:nginx/stable
$ sudo apt-get update
</code></pre>

<p>Once those commands have completed successfully, we can install Nginx.</p>

<pre><code>$ sudo apt-get install -y nginx
</code></pre>

<p>After the installation is complete, we should have a fully functioning web server. Test this out by visiting <a href="http://192.168.33.10/">http://192.168.33.10/</a>. You should see the default Nginx welcome page. Additionally, if you look in the <code>MyVagrant/html</code> directory, you should see a new file called <code>index.nginx-debian.html</code>.</p>

<p><em>But where did that URL come from? And the HTML file?</em></p>

<p>The URL was set when we edited <code>config.vm.network</code> in our <code>Vagrantfile</code>. We set <code>private_network</code> to an ip address of <code>192.168.33.10</code>.</p>

<p>The second edit we made was to <code>config.vm.synced_folder</code> and we <em>synced</em> <code>html</code> to <code>/var/www/html</code>. The first argument is the folder on our <em>local</em> machine relative to the <code>Vagrantfile</code> and the second argument is the folder on our <em>virtual machine</em>. The syncing gives us access to our virtual machine <em>through</em> our local filesystem. In our case, <code>/var/www/html</code> is the default web root for Nginx and we can get access to those files via the local <code>html</code> folder.</p>

<p>If you closed it, re-visit <a href="http://192.168.33.10/">http://192.168.33.10/</a>. Now open up <code>MyVagrant/html/index.nginx-debian.html</code> and make a change. Modify some text, change a style, anything you'd like. Save your edits and then refresh that page in your browser. You should see your changes immediately reflected! As you can see, <a href="https://www.vagrantup.com/docs/getting-started/synced_folders.html" title="Vagrant Synced Folders">synced folders</a> are a powerful feature of Vagrant.</p>

<p>We won't get any deeper into Nginx, but you can explore it's <a href="http://nginx.org/en/docs/beginners_guide.html" title="Beginner's Guide to Nginx">configuration</a> on your own.</p>

<h6 id="mysql57">MySQL 5.7</h6>

<p>Most websites need a data store. <a href="https://www.mysql.com/" title="MySQL">MySQL</a> is an immensely popular option, and one that is quite easy to install. If you aren't still, log back in to the virtual machine using <code>vagrant ssh</code>.</p>

<p>Again, the Ubuntu repositories hold an older version of MySQL. As such, we need to take a few extra steps to get access to MySQL 5.7. Run the following commands first:</p>

<pre><code>$ wget http://dev.mysql.com/get/mysql-apt-config_0.3.5-1ubuntu14.04_all.deb
$ sudo dpkg -i mysql-apt-config_0.3.5-1ubuntu14.04_all.deb
</code></pre>

<p>You will be prompted to set some configuration options. On the initial screen select <code>Server</code> and hit return. Then arrow down to select <code>mysql-5.7-dmr</code> and hit return. Then, again, arrow down to <code>Apply</code> and hit return. You will then be returned to the command-line. Continue with:</p>

<pre><code>$ rm mysql-apt-config_0.3.5-1ubuntu14.04_all.deb
$ sudo apt-get update
$ sudo apt-get install -y mysql-server-5.7
</code></pre>

<p>You will be prompted to input and confirm a password for the root user. Once installation is complete, you can access MySQL with <code>mysql -u root -p</code>. You will be asked for the password which you just created and once you are authenticated, you can interact with MySQL using it's command-line interface.</p>

<h6 id="php7">PHP7</h6>

<p>Finally, let's install <a href="http://php.net/" title="PHP">PHP7</a>, the newest version. It's fast. Almost twice as fast as the previous version, 5.6 (<em>mileage may vary of course</em>). Once again, let's add a repository in order to get version 7.0 and install the package.</p>

<pre><code>$ sudo add-apt-repository -y ppa:ondrej/php
$ sudo apt-get update
$ sudo apt-get install -y php7.0-fpm php7.0-cli
</code></pre>

<p>Depending on your application and use-case, you may need to add some PHP extensions. For instance, since we just installed MySQL, let's install that extension.</p>

<pre><code>$ sudo apt-get install -y php7.0-mysql
</code></pre>

<p>Not all extensions have been upgraded for PHP7, although the majority of them have. If you are in doubt, check <a href="https://github.com/gophp7/gophp7-ext/wiki/extensions-catalog" title="PHP7 Extensions Catalog">this resource</a>.</p>

<p>We also need to make a few changes to the Nginx configuration in order to a) serve .php files, and b) use PHP7. On the virtual machine edit the file <code>/etc/nginx/sites-available/default</code>. For instance, run <code>sudo nano /etc/nginx/sites-available/default</code>. We need to edit the following lines to add <code>index.php</code>. Change:</p>

<pre><code># Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;  
</code></pre>

<p>to:</p>

<pre><code># Add index.php to the list if you are using PHP
index index.php index.html index.htm index.nginx-debian.html;  
</code></pre>

<p>We also need to uncomment and edit a few lines of a location block. Look for:</p>

<pre><code># location ~ \.php$ {
#     include snippets/fastcgi-php.conf;
#
#     # With php5-cgi alone:
#     fastcgi_pass 127.0.0.1:9000;
#     # With php5-fpm:
#     fastcgi_pass unix:/var/run/php5-fpm.sock
# }
</code></pre>

<p>And change it to:</p>

<pre><code>location ~ \.php$ {  
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
}
</code></pre>

<p>Exit and save the changes, then restart Nginx.</p>

<pre><code>$ sudo service nginx restart
</code></pre>

<p>If you visit <a href="http://192.168.33.10/">http://192.168.33.10/</a> again, you should see no change, but it should still work. Let's create a simple .php file to test PHP. in our <code>MyVagrant/html</code> directory, create a file <code>index.php</code> and add this line:</p>

<pre><code class="language-php">&lt;?php phpinfo(); ?&gt;  
</code></pre>

<p>Save the file, and revisit <a href="http://192.168.33.10/">http://192.168.33.10/</a>. You should now be greeted with the the default PHP info page.</p>

<h6 id="conclusion">Conclusion</h6>

<p>Throughout this tutorial we have managed to install Vagrant and VirtualBox and spin up a quick Ubuntu 14.04 virtual machine. Then we were able to install the following components:</p>

<ul>
<li>Nginx 1.8.x</li>
<li>MySQL 5.7</li>
<li>PHP7</li>
</ul>

<p>With a few small configuration changes we successfully served a PHP page and edited files in our web-server root via the synced <code>MyVagrant/html</code> folder on our local filesystem.</p>

<p><em>Photo by <a href="https://unsplash.com/photos/NKSGuJzExIo">Paul Itkin</a> at <a href="https://unsplash.com/">Unsplash</a></em></p>]]></content:encoded></item><item><title><![CDATA[Magento 2 Using PHP7, Nginx, and Ubuntu 14.04]]></title><description><![CDATA[<p>Anyone that has dealt with Magento 1.x in the past no doubt has the war stories and scars to prove it. I am no different. It's a beast and I've sworn it off. Again and again. But with e-commerce, I've found it to be a circular argument. A recent</p>]]></description><link>http://blog.analoglifestyle.com/magento-2-using-php7-nginx-and-ubuntu-14-04/</link><guid isPermaLink="false">e9b3e78b-9289-4950-8422-9e9762167a2c</guid><category><![CDATA[Magento]]></category><category><![CDATA[php7]]></category><category><![CDATA[nginx]]></category><category><![CDATA[mysql]]></category><category><![CDATA[vagrant]]></category><category><![CDATA[ubuntu]]></category><dc:creator><![CDATA[Kevin DeBernardi]]></dc:creator><pubDate>Thu, 03 Mar 2016 22:49:00 GMT</pubDate><media:content url="http://blog.analoglifestyle.com/content/images/2016/03/photo-1439556838232-994e4c0d3b7c.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://blog.analoglifestyle.com/content/images/2016/03/photo-1439556838232-994e4c0d3b7c.jpg" alt="Magento 2 Using PHP7, Nginx, and Ubuntu 14.04"><p>Anyone that has dealt with Magento 1.x in the past no doubt has the war stories and scars to prove it. I am no different. It's a beast and I've sworn it off. Again and again. But with e-commerce, I've found it to be a circular argument. A recent project has brought me to the doorstep of Bigcommerce and I lament the drawbacks it has,  and then I long for my Shopify days, and then, once again, ponder the power of Magento (plus, we're at version 2). I pop from one to the other, around and around, never satisfied or completely won over. I suppose there is something to be said about life in that statement, but no matter.</p>

<p>Since my previous build of Magento 1.8.x a year or two ago I have improved immensely as a developer and have continued to grow and refine these skills. Now, it is far less of a chore to spin up a quick box and test something out. It wasn't always that way for me, and in those times I relied on the community and those resources to help get me through. Here's a bit of return on that. I hope this small tutorial can get someone else through and perhaps connect a few dots. So let's start with our box.</p>

<p><strong>Note:</strong> <em>This should only be used for testing and playing. Nothing here is production ready, hardened, or best-in-class!</em></p>

<p><strong>Note:</strong> <em>If you are looking for a simple, modern LEMP stack, see my article <a href="http://blog.analoglifestyle.com/simple-modern-lemp-using-vagrant" title="Simple, Modern LEMP Using Vagrant">Simple, Modern LEMP Using Vagrant</a>.</em></p>

<h6 id="vagrantandubuntu1404">Vagrant and Ubuntu 14.04</h6>

<p>Let's begin with spinning up a bare-bones <a href="https://www.vagrantup.com/docs/getting-started/">Vagrant</a> box using Ubuntu 14.04. The <a href="https://www.vagrantup.com/docs/vagrantfile/"><code>Vagrantfile</code></a> below will get you started, but feel free to modify it as you please. Also note that this step is optional. If you have a bare-bones Ubuntu 14.04 box, you can use it in place of this one.</p>

<pre><code>Vagrant.configure(2) do |config|

    config.vm.box = "ubuntu/trusty64"
    config.vm.network "forwarded_port", guest: 22, host: 7842

    ## Set the IP below to your own, and edit your hosts file if you'd like
    config.vm.network "private_network", ip: "192.168.56.102"

    ## Feel free to modify the hostname below
    config.vm.hostname = "magento.vm"

    ## Modify the path below to your synched folder
    ## The path below is relative to this Vagrantfile
    config.vm.synced_folder "../source/magento/", "/var/www", type: "nfs"

    config.vm.provider "virtualbox" do |vb|
        # Customize the amount of memory on the VM:
        vb.memory = "4096"
        vb.cpus = "4"
        vb.name = "magento"
    end

end  
</code></pre>

<p>Go ahead and spin that up on the command line.</p>

<pre><code>$ vagrant up
</code></pre>

<h6 id="letsinstallphp7">Let’s Install PHP7</h6>

<p>Once you have a bare-bones Ubuntu server to SSH into, go ahead and do that.</p>

<pre><code>$ vagrant ssh
</code></pre>

<p>Now that you are in the server, let's run a few commands to set up PHP7. A lot of these steps are from a great <a href="https://www.digitalocean.com/community/tutorials/how-to-upgrade-to-php-7-on-ubuntu-14-04" title="How To Upgrade to PHP 7 on Ubuntu 14.04">DigitalOcean article</a> covering the same topic. Reference it for a more in-depth explanation. We need to begin by adding a repository to use with apt-get in order to install PHP7.</p>

<pre><code>$ sudo add-apt-repository -y ppa:ondrej/php
$ sudo apt-get update
</code></pre>

<p>Once the repository is added and we have updated apt-get, let's install the package and the necessary PHP extensions that Magento2 requires (it's a long list).</p>

<pre><code>$ sudo apt-get install -y php7.0-fpm php7.0-mysql php7.0-cli php7.0-mcrypt php7.0-curl php7.0-gd php7.0-intl php7.0-xsl php7.0-zip php7.0-mbstring
</code></pre>

<p>That should complete without issue and once you are done you can run php -v, and you will see something resembling:</p>

<pre><code>PHP 7.0.4-1+deb.sury.org~trusty+1 (cli) ( NTS )  
Copyright (c) 1997-2016 The PHP Group  
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies  
with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies  
</code></pre>

<p>With that, we have PHP7! Now on to Nginx.</p>

<h6 id="servingwithspeed">Serving with Speed</h6>

<p>A quick note on why Nginx. I have found it to be fast, especially with Magento. That's it. I am not interested in much more than that in this case. So let's get it installed. Again I am using an additional repository in order to get the most recent stable version of Nginx (1.8.x at this time).</p>

<pre><code>$ sudo add-apt-repository -y ppa:nginx/stable
$ sudo apt-get update
</code></pre>

<p>And install.</p>

<pre><code>$ sudo apt-get install -y nginx
</code></pre>

<p>Congratulations, grab a beer! You should be able to visit the IP address from your <code>Vagrantfile</code> (192.168.56.102 in this tutorial) and be greeted with the default Nginx Welcome page.</p>

<h6 id="sneakaquickonein">Sneak a Quick One In</h6>

<p>We are going to need MySQL for the Magento installation as well, and since there isn't much to getting that going, just run the following command to install it and set the root password.</p>

<pre><code>$ sudo apt-get install -y mysql-server-5.6
</code></pre>

<p>While we're here, let's just quickly set up a database for Magento which we will need a bit later. Go ahead and drop in to MySQL.</p>

<pre><code>$ mysql -u root -p
</code></pre>

<p>And on the MySQL prompt, enter:</p>

<pre><code>create database magento;  
exit;  
</code></pre>

<h6 id="staycomposed">Stay Composed</h6>

<p>We are going to need Composer to run our installation of Magento via the command line. Let's run a quick installation of that as well.</p>

<pre><code>$ sudo curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer
</code></pre>

<h6 id="staysecure">Stay Secure</h6>

<p>One semi-final server-side command. Let's pop in a self-signed certificate so that we can reach the admin side of Magento over https.</p>

<pre><code>$ sudo mkdir /etc/nginx/ssl
$ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/magento-self.key -out /etc/nginx/ssl/magento-self.crt
</code></pre>

<p>Wow, okay, maybe another sip of beer. Take a breath and get ready, because now, <em>finally</em>, we get to Magento.</p>

<h6 id="thepayoffstep1">The Payoff, Step 1</h6>

<p>As a glutton for punishment, I opt to install Magento2 entirely from the command line using Composer. As such, we need to secure a, <em>ahem</em>, secure key from Magento Connect to do that. Visit <a href="http://devdocs.magento.com/guides/v2.0/install-gde/prereq/connect-auth.html">this link</a>, log in to, or create, your account and follow the instructions. We will need to reference this key shortly.</p>

<p>Key in hand, let's continue. Navigate to the <code>/var/www</code> directory on the server. There will be a folder named <code>html</code> which holds the default Nginx page we celebrated earlier with our beer, but we will ignore that. From here we will run composer to download the Magento2 CE Metapackage into a new folder called <code>magento</code>.</p>

<pre><code>$ composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition magento
</code></pre>

<p>You will immediately be prompted for your username. This is where we need the key we just created. Your username is the "Public Key" and the password is the "Private Key." You will be prompted as to whether you want you're credentials stored. Feel free to answer yes or no, but I suggest yes. After that… wait for Composer to do its thing. It will be a little bit, you may want some more of that beer. Perhaps a second. This is Magento after all. At the end of this, you should have a folder <code>/var/www/magento</code>.</p>

<h6 id="butwait">But Wait!</h6>

<p>Towards the end of the Composer install above, the command line may say "Could not fetch…"! Don't worry, just follow the provided instructions, but you will need a GitHub account. And we're back on track.</p>

<h6 id="thepayoffstep2">The Payoff, Step 2</h6>

<p>Can you feel that? We're nearly there. Let's blindly set some permissions and ownership. <em>Keep in mind that this is a test install and blindly copying and pasting commands to change permissions and ownership is not always prudent.</em> In this case, let's go for it. Navigate to <code>/var/www/magento</code> and paste the following commands:</p>

<pre><code>$ chown -R :www-data .
$ find . -type d -exec chmod 770 {} \; &amp;&amp; find . -type f -exec chmod 660 {} \; &amp;&amp; chmod u+x bin/magento
</code></pre>

<p>Note the period (".") at the end of the first line. Make sure that is included. These commands will take a little time to run in order to iterate over all the files and folders.</p>

<p>Now the cool part. Navigate in to the <code>/var/www/magento/bin</code> folder and let's run a command.  This command is quite long and has a lot of options in it. <em>Replace the all-cap placeholders with your own information.</em></p>

<pre><code>./magento setup:install --base-url=http://YOUR-IP-OR-URL/ --db-host=localhost --db-name=magento --db-user=root --db-password=YOUR-MYSQL-ROOT-PASSWORD --admin-firstname=YOUR-FIRST-NAME --admin-lastname=YOUR-LAST-NAME --admin-email=THE-ADMIN-EMAIL --admin-user="THE ADMIN USERNAME" --admin-password=THE-ADMIN-PASSWORD --language=en_US --currency=USD --timezone=America/New_York --use-rewrites=1
</code></pre>

<p>And with that, we have Magento2! Note the URI at the end of the above command which denotes the Admin URI. We will need that to log in to the Admin section of our installation.</p>

<p>So go ahead and visit that IP or URL we have from the <code>Vagrantfile</code>.</p>

<h6 id="waitwhat">Wait, What!?</h6>

<p>Still see the default Nginx landing page? Sure do! We have two final steps to get this guy into working order. The first is the Nginx config file, and finally, we implement a quick cron job.</p>

<h6 id="configconfigconfig">Config, Config, Config</h6>

<p>Let's bang this out and get going. I’ll leave the details out of it, but run the following command to edit our default site config:</p>

<pre><code>$ sudo nano /etc/nginx/sites-available/default
</code></pre>

<p>Delete everything that is in there, and replace it with the following (again, replace the all-caps with your information):</p>

<pre><code>upstream fastcgi_backend {  
    server unix:/var/run/php/php7.0-fpm.sock;
}

server {  
    listen 443 ssl;
    server_name YOUR-IP-OR-URL;
    set $MAGE_ROOT /var/www/magento;
    set $MAGE_MODE default;
    ssl_certificate /etc/nginx/ssl/magento-self.crt;
    ssl_certificate_key /etc/nginx/ssl/magento-self.key;
    include /var/www/magento/nginx.conf.sample;
}

server {  
    listen 80;
    server_name YOUR-IP-OR-URL;
    set $MAGE_ROOT /var/www/magento;
    set $MAGE_MODE default;
    include /var/www/magento/nginx.conf.sample;
}
</code></pre>

<p>Now hit Nginx with a restart sudo service nginx restart and now you should be able to visit your IP or URL in the browser and be greeted with Magento2!</p>

<h6 id="croncroncron">Cron, Cron, Cron</h6>

<p>With our front-end up and running, take a peek at the Admin side of things. You can append the admin URI you noted at the end of the Magento installation and use the info you entered in that extra long Magento install command. You should be able to log in without problem, but you will see a warning immediately.</p>

<pre><code>One or more indexers are invalid. Make sure your Magento cron job is running.  
</code></pre>

<p>Well, fact is, that cron job is not running! Let's make it run. Enter the following command.</p>

<p><strong>Note:</strong> <em>The user below is specific to Vagant, so if you aren't using Vagrant, enter the user that Magento is running under.</em></p>

<pre><code>$ sudo crontab -u vagrant -e
</code></pre>

<p>Choose your editor of choice and then enter the following after the comments in the file:</p>

<pre><code>*/1 * * * * /usr/bin/php -c /etc/php/7.0/cli/php.ini /var/www/magento/bin/magento cron:run &gt; /var/www/magento/var/log/magento.cron.log&amp;
*/1 * * * * /usr/bin/php -c /etc/php/7.0/cli/php.ini /var/www/magento/update/cron.php &gt; /var/www/magento/var/log/update.cron.log&amp;
*/1 * * * * /usr/bin/php -c /etc/php/7.0/cli/php.ini /var/www/magento/bin/magento setup:cron:run &gt; /var/www/magento/var/log/setup.cron.log&amp;
</code></pre>

<p>And that, my friend, is it. If you refresh the Admin side, the cron warning should be gone and you are the proud owner of a Magento2 installation. And now that you have all the information to get back up and running, feel free to blow this one up! Explore, change, break and see what’s under the hood. There's a lot to know.</p>

<p><em>Photo by <a href="https://unsplash.com/photos/tVCu6V-IcSI">kazuend</a> at <a href="https://unsplash.com/">Unsplash</a></em></p>]]></content:encoded></item><item><title><![CDATA[Shopify Blog Entry With A Featured Image]]></title><description><![CDATA[<p>A common feature request, and the subject of a multitude of workarounds and hacks, has been for a featured image in Shopify blog entries. This has historically been solved with your common Shopify hacks: add the image as the first item in the text and pull it out dynamically, use</p>]]></description><link>http://blog.analoglifestyle.com/shopify-blog-entry-with-a-featured-image/</link><guid isPermaLink="false">519fdfd9-3427-40f4-b74b-54543d1eae44</guid><category><![CDATA[shopify]]></category><dc:creator><![CDATA[Kevin DeBernardi]]></dc:creator><pubDate>Tue, 03 Nov 2015 22:41:00 GMT</pubDate><media:content url="http://blog.analoglifestyle.com/content/images/2016/03/photo-1448908828366-ae00562d5fde.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://blog.analoglifestyle.com/content/images/2016/03/photo-1448908828366-ae00562d5fde.jpg" alt="Shopify Blog Entry With A Featured Image"><p>A common feature request, and the subject of a multitude of workarounds and hacks, has been for a featured image in Shopify blog entries. This has historically been solved with your common Shopify hacks: add the image as the first item in the text and pull it out dynamically, use metafields, name the image with the id of the blog entry, etc.</p>

<p>It seems that Shopify has listened as a new field has shown up when you create a blog entry. The new field works as expected, and now adding a featured image to an entry is a simple task.</p>

<p><img src="http://blog.analoglifestyle.com/content/images/2016/03/featured_image.jpg" alt="Shopify Blog Entry With A Featured Image"></p>

<p>To use that image within your Liquid templates took a bit more digging, but it is syntactically as you would expect:</p>

<pre><code>&lt;img src="{{ article.image | article_img_url: 'master' }}" /&gt;  
</code></pre>

<p>As with other image tags, you can specify various <a href="https://docs.shopify.com/themes/liquid/filters/url-filters#size-parameters" title="Shopify Image Sizes">image sizes</a> ('master' above) within the URL filter.</p>

<p><em>Photo by <a href="https://unsplash.com/photos/pRQ_G-un4xs">Natasha Vasiljeva</a> at <a href="https://unsplash.com/">Unsplash</a></em></p>]]></content:encoded></item><item><title><![CDATA[Dynamically Remove a Summernote Instance with jQuery]]></title><description><![CDATA[I’ve been developing a page that has multiple instances of Summernote. An issue arose when the user attempted to remove a particular instance.]]></description><link>http://blog.analoglifestyle.com/dynamically-remove-a-summernote-instance-with-jquery/</link><guid isPermaLink="false">a4658515-39a5-4287-b051-21e0e056788a</guid><category><![CDATA[jquery]]></category><category><![CDATA[summernote]]></category><dc:creator><![CDATA[Kevin DeBernardi]]></dc:creator><pubDate>Mon, 20 Jul 2015 04:21:00 GMT</pubDate><media:content url="http://blog.analoglifestyle.com/content/images/2016/03/photo-1449168013943-3a15804bb41c.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://blog.analoglifestyle.com/content/images/2016/03/photo-1449168013943-3a15804bb41c.jpg" alt="Dynamically Remove a Summernote Instance with jQuery"><p>I’ve been developing a page that gets loaded with multiple instances of the WYSIWYG text editor <a href="http://summernote.org/" title="Summernote, A Super Simple WYSIWYG Editor on Bootstrap">Summernote</a>. An issue arose when the user attempted to remove a node which contained a Summernote instance. The jQuery <a href="http://api.jquery.com/remove/" title="jQuery's .remove() method">.remove()</a> method was attached to a button, which would remove the node that contained the Summernote instance. When the form was submitted, I would get an error:</p>

<pre><code>Uncaught TypeError: Cannot read property 'val' of undefined  
</code></pre>

<p>I couldn’t track down the root of the error, but Summernote was looking for a val() that it couldn’t find. The correct node and child elements had been removed from the DOM, but Summernote seemed to think it was still there. I tried the <a href="http://summernote.org/deep-dive/#destroy" title="Summernote's .destroy() method">.destroy()</a> method of Summernote before the jQuery .remove() to no avail. In the end, I ended up using the jQuery method <a href="http://api.jquery.com/detach/" title="jQuery's .detach() method">.detach()</a> instead of .remove() which “keeps all jQuery data associated with the removed elements.” On submission, Summernote acts correctly and, since the DOM node had been removed, my data persisted correctly in the back-end.</p>

<p><em>Photo by <a href="https://unsplash.com/photos/n3t4fIuVzLA">Cameron Kirby</a> at <a href="https://unsplash.com/">Unsplash</a></em></p>]]></content:encoded></item><item><title><![CDATA[Left-, Right-, and Center-Aligned Headings]]></title><description><![CDATA[<p>While implementing a range slider input for a recent project I needed headings for the three available stop-points, one left-aligned, one centered, and one right-aligned. After a bit of verbose HTML and CSS, I refined it several times and settled on the following code.</p>

<p><img src="http://blog.analoglifestyle.com/content/images/2016/03/range_slider.gif" alt=""></p>

<h6 id="css">CSS</h6>

<pre><code class="language-css">.ranges {
    text-align: center;
}

.ranges span:</code></pre>]]></description><link>http://blog.analoglifestyle.com/left-right-and-center-aligned-headings/</link><guid isPermaLink="false">551cd38f-9239-45b7-b702-43d93efc7802</guid><category><![CDATA[css]]></category><category><![CDATA[html]]></category><dc:creator><![CDATA[Kevin DeBernardi]]></dc:creator><pubDate>Sat, 07 Feb 2015 22:36:00 GMT</pubDate><media:content url="http://blog.analoglifestyle.com/content/images/2016/03/photo-1439792675105-701e6a4ab6f0-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://blog.analoglifestyle.com/content/images/2016/03/photo-1439792675105-701e6a4ab6f0-1.jpg" alt="Left-, Right-, and Center-Aligned Headings"><p>While implementing a range slider input for a recent project I needed headings for the three available stop-points, one left-aligned, one centered, and one right-aligned. After a bit of verbose HTML and CSS, I refined it several times and settled on the following code.</p>

<p><img src="http://blog.analoglifestyle.com/content/images/2016/03/range_slider.gif" alt="Left-, Right-, and Center-Aligned Headings"></p>

<h6 id="css">CSS</h6>

<pre><code class="language-css">.ranges {
    text-align: center;
}

.ranges span:first-child {
    float: left;
}

.ranges span:last-child {
    float: right;
}
</code></pre>

<h6 id="html">HTML</h6>

<pre><code class="language-html">&lt;div class="ranges"&gt;  
    &lt;span&gt;Left&lt;/span&gt;
    Middle
    &lt;span&gt;Right&lt;/span&gt;
&lt;/div&gt;  
</code></pre>

<p><em>Photo by <a href="https://unsplash.com/photos/DjlKxYFJlTc">Elliott Engelmann</a> at <a href="https://unsplash.com/">Unsplash</a></em></p>]]></content:encoded></item><item><title><![CDATA[AngularJS and Page Refresh]]></title><description><![CDATA[<p>I’ve been building out a recent project, <a href="https://jazzleadsheets.com/">Jazzleadsheets.com</a>, on <a href="https://angularjs.org/">AngularJS</a> and <a href="https://magento.com/">Magento</a> being served by <a href="http://nginx.org/">Nginx</a>, and ran into a frustrating problem. When I refreshed any page other than the index, the site would throw a <code>500 Internal Server Error</code>. Additionally, if I entered in a nonsense URL,</p>]]></description><link>http://blog.analoglifestyle.com/angularjs-and-page-refresh/</link><guid isPermaLink="false">83e672c2-925d-4324-9057-b326acede38d</guid><category><![CDATA[Magento]]></category><category><![CDATA[nginx]]></category><category><![CDATA[angularjs]]></category><dc:creator><![CDATA[Kevin DeBernardi]]></dc:creator><pubDate>Mon, 14 Apr 2014 21:27:00 GMT</pubDate><media:content url="http://blog.analoglifestyle.com/content/images/2016/03/photo-1451186859696-371d9477be93.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://blog.analoglifestyle.com/content/images/2016/03/photo-1451186859696-371d9477be93.jpg" alt="AngularJS and Page Refresh"><p>I’ve been building out a recent project, <a href="https://jazzleadsheets.com/">Jazzleadsheets.com</a>, on <a href="https://angularjs.org/">AngularJS</a> and <a href="https://magento.com/">Magento</a> being served by <a href="http://nginx.org/">Nginx</a>, and ran into a frustrating problem. When I refreshed any page other than the index, the site would throw a <code>500 Internal Server Error</code>. Additionally, if I entered in a nonsense URL, which should be directed back to the homepage, I received the same 500 error. I was stumped.</p>

<p>After fruitless hours researching and testing, I made a breakthrough. I realized that in my application config I implemented “HTML5 Mode” with:</p>

<pre><code>.config(['$locationProvider', function($locationProvider) {
    $locationProvider.html5Mode(true);
}])
</code></pre>

<p>This allowed me to dump the hash-bang syntax (example.com/#/catalog) and present the user with well-formatted URLs (example.com/catalog). This was also the root of the issue. Commenting out the code segment above resulted in hash-bang URLs, but allowed me to refresh any page correctly as AngularJS knew how to route those. From there I put the pieces together and realized that Nginx was configured correctly to route the requests for AngularJS. The answer lie in a single addition to my Nginx location block:</p>

<pre><code>location / {  
    ...
    try_files $uri /example.html;
    ...
}
</code></pre>

<p>Where <code>example.html</code> is replaced by the base file you want to route requests to. In my case, <code>index.html</code>. With this addition and a quick restart of Nginx, my page refreshes worked like a boss.</p>

<p><em>Photo by <a href="https://unsplash.com/photos/6-jTZysYY_U">NASA</a> at <a href="https://unsplash.com/">Unsplash</a></em></p>]]></content:encoded></item><item><title><![CDATA[How To Reorder Admin Fields For Products In Magento 1.8.x]]></title><description><![CDATA[<p>It’s common knowledge that Magento can be a bit of a beast to modify and customize. On a recent project I wanted to add a custom field to the admin side of a product, which is a simple process, but I also wanted to reorder them within the tab.</p>]]></description><link>http://blog.analoglifestyle.com/how-to-reorder-admin-fields-for-products-in-magento-1-8-x/</link><guid isPermaLink="false">1a524d46-9083-4794-9871-7da8741f154f</guid><category><![CDATA[Magento]]></category><dc:creator><![CDATA[Kevin DeBernardi]]></dc:creator><pubDate>Sun, 09 Mar 2014 21:24:00 GMT</pubDate><media:content url="http://blog.analoglifestyle.com/content/images/2016/03/photo-1449057528837-7ca097b3520c.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://blog.analoglifestyle.com/content/images/2016/03/photo-1449057528837-7ca097b3520c.jpg" alt="How To Reorder Admin Fields For Products In Magento 1.8.x"><p>It’s common knowledge that Magento can be a bit of a beast to modify and customize. On a recent project I wanted to add a custom field to the admin side of a product, which is a simple process, but I also wanted to reorder them within the tab. My custom field needed to come after the "Name" field, not at the end (after "Country of Manufacture") of the options. Simple request, simple execution, but hours of searching for the answer.</p>

<p><img src="http://blog.analoglifestyle.com/content/images/2016/03/custom_attribute.jpg" alt="How To Reorder Admin Fields For Products In Magento 1.8.x"></p>

<p><strong>Question:</strong> How do I reorder the admin fields within the "General" product tab?</p>

<p><strong>Answer:</strong> Magento orders these fields according to a sort order pulled from the database. With all the foreign keys and EAV structure this took quite a while to track down. Ultimately, the table you need to modify is named <code>eav_entity_attribute</code>, but you need to first find the ID of the element you would like to change. This can be found in the <code>eav_attribute</code> table and is called <code>attribute_id</code>. Once you have that number, you can navigate to the <code>eav_entity_attribute</code> table and find the ID in the <code>attribute_id</code> column. Make note of the <code>attribute_group_id</code> as these are the other elements that are in the tab in the admin section. By default there are 29 elements, plus the one you added, and you will notice the <code>sort_order</code> column. Your custom element will have the value of 30 (if this is the first custom attribute you added to Magento) and is thus last in the sort order. In my use case above, I wanted my custom attribute to be after the "Name" field which means setting the value of the <code>sort_order</code> field to 2. Before you make the change, you need to make a space for it, so you need to increment every value in <code>sort_order</code> by 1 starting from the value you want your element to be. This is easily accomplished with the MySQL query below:</p>

<pre><code>UPDATE eav_entity_attribute SET sort_order=sort_order+1 WHERE attribute_group_id = 7 AND sort_order &gt; 1  
</code></pre>

<p>Make sure that the value in <code>sort_order &gt; 1</code> is set appropriately for your own placement. Since I want my custom element to appear second, I need to update the values for 2 through 30. The sort order is now appearing as 1, 3, 4, 5, 6, etc. which leaves the spot for my custom attribute. Now, it’s merely a fact of changing the sort order value for my element from 31 to 2! If you go back to the admin page and refresh, your custom attribute should appear in it’s correct place.</p>

<p><em>Photo by <a href="https://unsplash.com/photos/pGMjBhsf4Q8">Paul Itkin</a> at <a href="https://unsplash.com/">Unsplash</a></em></p>]]></content:encoded></item><item><title><![CDATA[Simple Git on MediaTemple]]></title><description><![CDATA[<p>It took me quite a while to get all this information together and working. Instead of enduring the search over again, I am writing it down for myself and any others that may find it useful.</p>

<p>1) Visit <a href="http://ryanflorence.com/deploying-websites-with-a-tiny-git-hook/">Ryan Florence’s site</a> for the bulk of the info. <br>
2) When</p>]]></description><link>http://blog.analoglifestyle.com/simple-git-on-mediatemple/</link><guid isPermaLink="false">bfbda381-ff17-4e43-9f49-4fd454e6c06c</guid><category><![CDATA[git]]></category><category><![CDATA[mediatemple]]></category><dc:creator><![CDATA[Kevin DeBernardi]]></dc:creator><pubDate>Sun, 10 Apr 2011 21:01:00 GMT</pubDate><media:content url="http://blog.analoglifestyle.com/content/images/2016/03/photo-1451188502541-13943edb6acb.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://blog.analoglifestyle.com/content/images/2016/03/photo-1451188502541-13943edb6acb.jpg" alt="Simple Git on MediaTemple"><p>It took me quite a while to get all this information together and working. Instead of enduring the search over again, I am writing it down for myself and any others that may find it useful.</p>

<p>1) Visit <a href="http://ryanflorence.com/deploying-websites-with-a-tiny-git-hook/">Ryan Florence’s site</a> for the bulk of the info. <br>
2) When you add the web-server’s repository, and this is specifically for MediaTemple GridServer users, the SSH url should be:</p>

<pre><code>ssh://serveradmin%mt-example.com@mt-example.com/home/#####/domains/mt-example.com/html/  
</code></pre>

<p>where ##### is the GridServer cluster you are hosted on.</p>

<p><em>Photo by <a href="https://unsplash.com/photos/E7q00J_8N7A">NASA</a> at <a href="https://unsplash.com/">Unsplash</a></em></p>]]></content:encoded></item></channel></rss>