Tuesday, September 3, 2013

Eliminate Apache "NameVirtualHost *:80 has no VirtualHosts", Or: Using Manual Virtual Hosts and Zend Server Application Deployment


The Problem

You restart Apache and get a nice NameVirtualHost *:80 has no VirtualHosts warning message, on the screen, or in the error log. Why, and how do you get rid of it?

The cause of this is simple, although the warning seems counterintuitive, since most likely you're seeing it after deliberately creating one or more virtual hosts in your Apache configuration.


If you're using Include configuration files, look carefully in the main configuration file, and in the Included files.  You will see multiple occurrences of the NameVirtualHost directive, like this:

In one configuration file (for example, httpd.conf):
NameVirtualHost *:80

In another configuration file (for example, extra/httpd-vhosts.conf):
NameVirtualHost *:80

The solution is to comment out the second one that is processed, and you will eliminate the warning.


How this manifested

For me, this occurred when I manually added a vhost to my development workstation, which is running Zend Server 6. I did not want to use its Application Deployment capability for local development, since I preferred in this case to just edit code, flip to my browser, and refresh.


I reserve Zend Server Application Deployment for deploying to a remote server, although I certainly test deployments locally first. There is a simple way to deploy once, and have edited code auto-saved to the server, so it is NOT at all necessary to avoid Application Deployment in local development, but that is a topic for another post.

Anyway, /usr/local/zend/apache2/conf/httpd.conf originally contained this commented directive:

# Virtual hosts
#Include conf/extra/httpd-vhosts.conf

and /usr/local/zend/apache2/conf/extra/httpd-vhosts.conf originally contained the two dummy-host.example.com sample vhosts.  I commented these out and added my vhost:

# Virtual hosts
<VirtualHost *:10088>
    ServerName dev.florists.local
    ServerAdmin clark.e@zend.com
    DirectoryIndex index.php index.html

    SetEnv APPLICATION_ENV development

    DocumentRoot "/Users/eai/vhosts/florists/public"

    LogLevel warn

    php_value session.save_path "/path/to/my/development/session/directory"
    php_value upload_tmp_dir "/path/to/my/development/uploads/directory"

    <Directory /Users/eai/vhosts/florists/public>
        Options Indexes MultiViews FollowSymLinks
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} -s [OR]
        RewriteCond %{REQUEST_FILENAME} -l [OR]
        RewriteCond %{REQUEST_FILENAME} -d
        RewriteRule ^.*$ - [NC,L]
        RewriteRule ^.*$ /index.php [NC,L]
        Order allow,deny
        Allow from all
    </Directory>
</VirtualHost>


I then uncommented the #Include conf/extra/httpd-vhosts.conf line in httpd-vhosts.conf, and restarted apache with

$ sudo /usr/local/zend/bin/zendctl.sh restart-apache

and saw the warning:
Mon Sep 02 03:33:20 2013] [warn] NameVirtualHost *:10088 has no VirtualHosts

Looking at the two configuration files, this appeared in http.conf:
Include /usr/local/zend/apache2/conf.d/
#ZEND-{2F-blah-blah...}
NameVirtualHost *:10088

#ZEND-{13-blah-blah...}
Include "/usr/local/zend/etc/sites.d/zend-default-vhost-10088.conf"
#ZEND-{13-blah-blah...}

#ZEND-{2F-blah-blah...}
#ZEND-{AF-blah-blah...}
Include "/usr/local/zend/etc/sites.d/globals-*.conf"
Include "/usr/local/zend/etc/sites.d/vhost_*.conf"
#ZEND-{AF-blah-blah...}

And this was in http-vhosts.conf (this is what I hadn't paid any attention to):
#
# Use name-based virtual hosting.
#
NameVirtualHost *:10088

So, the directive was being processed twice.  This is merely a warning, since Apache will actually ignore the second directive and use only the first defined NameVirtualHost directive. If you're a Debian user and seeing this warning, take a peek at the ports.conf file.


How to Fix

Just comment out the second occurrence to be processed. In my case, this is the one in the main httpd.conf file, since the Include of the httpd-vhosts file comes before that line:

#ZEND-{2F-blah-blah...}
# Manually including conf/extra/httpd-vhosts.conf obviates this line - NameVirtualHost *:10088

#ZEND-{13-blah-blah...}

Restart again, and the warning is gone.


Tuesday, August 6, 2013

Use alternate SSH port with Zend Studio

To connect Zend Studio to a remote server using an alternate, non-standard SSH port (that is, other than port 22) you will do the following:
  • Create the connection.
  • View the properties of the connection.
  • Edit the port in the connection "Subsystem"

Create the connection

and specify only the hostname or IP address. Do not worry at this point about the port number. For instance, do not try to append the port to the hostname.

    Window | Open Perspective | Other | Remote System Explorer

    Window | Show View | Remote Systems


    Right-click in the blank area in the Remote Systems view, select New Connection then select SSH Only, click Next.

    Enter Host Name, Connection Name (a name for display purposes only), uncheck Verify host name, and click Next, th

    Under Available Services, click on Ssh / Sftp File Service, then click Finish.

    View the properties of the connection

    Expand the connection you just created, right-click on Sftp Files, and select Properties.  Click on Subsystem, and change the port number in the pane on the right. Click OK.

    Use the connection to view the remote files.

    Expand Sftp Files, expand either My Home or Root, enter the password (optionally selecting Save password) and click OK.

    Sunday, January 22, 2012

    Git happy - A Two-second Fix for OSX git: command not found


    After downloading and installing the appropriate git dmg from http://code.google.com/p/git-osx-installer/downloads/list?can=3, add a trailing slash to the end of the git file in paths.d as follows:

    sudo vi /etc/paths.d/git

    so it reads like this after you're finished:

    /usr/local/git/bin/

    Exit the current terminal window, open a new one. You're done.
    PS. You don't have to use vim if you really don't want to, but hey...

    Saturday, January 14, 2012

    An Excellent Start to the Year (or "Great is the Enemy of Good.")


    Let me read something to you, and tell you what it means to me. If you like, we can talk about it.
    This is important: my aim is not to make the perfect bread or pasta or mayonnaise or biscuits - the best I've ever had. It's to set a baseline to work off of. When I was writing "Walk on Water," about a renowned surgeon, more than one doctor noted the common saying "great is the enemy of good," meaning that when surgeons strive for greatness, they can cause harm when they might otherwise not have harmed had they simply strived for good. I've worked with the greatest perfectionist there is in the cooking world, and I love that hunt for the perfect sauce, the perfect custard, but here I'm after good. Only when we know good can we begin to inch up from good to excellent.
    And this...
    We must have craft before we have art, and craft is founded on fundamentals.
    These quotes are from a book my wife and I sometimes read in the kitchen. It was written by Michael Ruhlman, and is called "Ratio: The Simple Codes Behind the Craft of Everyday Cooking."


    True perfectionism hinders as much as it might inspire or encourage. Excellence, not perfectionism, should be what we strive for, and become the standard by which we operate.


    In "great is the enemy of good," great is perfectionism, born of vanity, ego, obsession, or a possible disorder. Whatever the cause, it is unhealthful. Good does not mean merely sufficient, good enough to get by, or mediocre. Good is a reasonable, healthy minimum given the constraints of time, ability, resources, and the true expectations of those affected by our efforts.

    So, this is not an assault on striving toward high standards, but recognizing that we should keep everything in perspective while doing the best we can, knowing that "only when we know good can we begin to inch up from good to excellent," and acknowledging that "we must have craft before we have art, and craft is founded on fundamentals."


    Get the fundamentals down pat, then build upon that platform a structure of excellence.


    That's what this little corner of the interwebs is about, primarily within the context of developing software, primarily in PHP. Why haven't I written more before now? I guess I know a thing or two about perfectionism...


    Have an Excellent Year!

    Saturday, September 24, 2011

    How to Quickly Rotate Several Image Files from Upside Down to Rightside Up in OSX


    Not exactly the PHP-related post I expected to write next... Many people, Mac users included, won't need this post. That's okay, because it isn't for you.  It's for Mac newbies, a description which I apply to myself.

    I'm using an extended keyboard, with the numeric keypad and inverted-T arrow keys.  I'll have to look at a regular keyboard and see what the equivalent keystrokes would be.

    Someone scanned 40-something pages of a document and emailed the resulting jpeg image files to me.  They were all upside down.  Here's what I did to get them right-side up, fairly quickly - though still a manual process - on the Mac under OSX.


    1. Open a Finder window showing all the files in a list view. Get into list view by clicking the second icon from the left immediately above the area in which the files appear.
    2. Select all of the image files by clicking on the file at the top of the list, pressing the shift key and, holding it down, press the down arrow key until all filenames are highlighted.
    3. Command-O to open all of them at once in the Preview application.
    4. Hold down the Command key with your right thumb.
    5. With your left hand, press the "R" key twice, to rotate the image right, until it is vertical. Do NOT release the Command key with your right thumb.
    6. Press the "S" key with your left hand to save the image.
    7. Release the command key under your right thumb, and press the down arrow key.
    8. Repeat steps 4 through 7 until you've finished with all the images.


    If this happens to you a lot, you could record this process and play it on another set of files using the built-in Automator Application.  That's for another day, though.

    If you find this useful, or if you have suggestions for improvements to this process, let me know.

    Thursday, March 31, 2011

    Ideas of March, or Thank you, Mr. Shiflett.

    We do need more blogging.  Tweets are fine for their intended purpose, but there is only so much idea one can squeeze into so little space.

    I like blogs because of what I learn from them; they encourage me to stay current, they expose me to new thoughts and they help me stay connected with the community.

    I like blogs precisely because they aren't real-time. They are the result of observation and reflection.  I get to read someone's more fully-developed thoughts, communicated in full sentences, with examples, and even paragraphs!  Blogging forces one to crystallize one's thoughts, and teaches us how to communicate more effectively.  True written communication is not dead.  Blogs make me think; I not only like that, I need it.

    I like being able to go back to a blog post I've bookmarked as a reference, finding again something I needed once, and need again from time to time. In addition, I get to see how the concept develops over time, as commentors contribute their thoughts and opinions on the subject.

    Blogs also inspire me to contribute some of what I may have learned along the way.  This is where I've fallen down, terribly, often believing that I really didn't have much to say that would be of use to others.

    I see otherwise now.  I've been teaching novice programmers PHP and Zend Framework with Zend Technologies since autumn 2008.  I get asked a lot of questions about programming, code design, object-oriented development, and testing.  Most of my colleagues are advanced developers, and they often blog about advanced techniques, and although those techniques help make a developer's life easier, some of the people I encounter daily aren't quite ready to take advantage of particularly advanced development practices.

    I pledge to blog more often, and help flatten out the learning curve for the newbies.  We were all newbies, once, and if we're committed to lifelong learning, and to keeping our skills current, we remain newbies, in at least one area, all the time.

    See you briefly on Twitter with a #ideasofmarch tweet.

    Zend Framework Autoloading - Finding Your Library Classes

    Attention Zend Framework beginners.  Since today is the final day for me to get around to contributing - in some small way - to The Ideas of March, which encourages people to blog more often, I offer up the following.

    If you find yourself using require_once statements in your Zend Framework applications in order for ZF to find your library classes, in spite of using Zend_Application - which you know establishes autoloading by default - then there is one simple thing you need to add to your application's config file, typically configs/application.ini, to fix the problem.  End your frustration, and read on.

    Assuming a directory structure something like this (my "vendor prefix" of EAI stands for Everetts Associates, Inc.):
    application/
    data/
    docs/
    library/
            EAI/
                Mail.php
    public/
    scripts/
    temp/
    tests/

    and a class named EAI_Mail in the Mail.php file, and assuming your library is on your include_path, all that is needed is a line like this in application.ini:

    autoloaderNamespaces[] = "EAI_"

    Zend Framework's autoloader is already configured to match class prefixes Zend_ and ZendX_.  What you're doing by adding the above line to the application's config file is register your library prefix/namespace with the autoloader.  The include_path was not your problem, the problem was that ZF wasn't acknowledging your class prefix.

    Now you can strip out those require_once statements for a bit of a performance boost.

    Happy coding.