PHP Portable Paths

Forward SlashFrankly, I don’t care about people wanting to run my code on a Windows box and it not working. But in reality, for some reason, there are people who write code using computers running the Microsoft Windows operating system. Why don’t they use a Mac, or if they don’t have or want to spend the money on a Mac, use Linux? That I do not know, but there are people, and they probably work in your company who use Windows and they think they can code.

Like I said, I don’t really care if my shit doesn’t run on Windows, but it is relatively trivial to write PHP code that can run on Windows and Linux, Mac and any operating system that can run PHP.

The only real obstacle to portability is directory paths. In my world, these are usually paths to configs or log directories.

The could be code like this.

$config = new Configuration(sprintf('conf/%s', $configFilename));

That’s not portable to Windows because of that forward slash.

What I could do is this.

$config = new Configuration(sprintf('conf%s%s', DIRECTORY_SEPARATOR, $configFilename));

Now instead of a forward slash, if this were running on Windows, it would use a backward slash, because Windows is backwards.

I took it one step more and wrote a static method in my Configuration class that looks like this.

public function static Path($path)
{
    if (DIRECTORY_SEPARATOR == '/') return $path;
    return str_replace('/', DIRECTORY_SEPARATOR, $path);
}

This method will replace all forward slashes with DIRECTOR_SEPARATOR. If the DIRECTOR_SEPARATOR is a forward slash, the path is just returned unchanged. If DIRECTOR_SEPARATOR is not a forward slash, forward slashes in path are replaced with what is DIRECTOR_SEPARATOR.

I do it this way because in my code, I still put the forward slash in. The default is that my code will be running on some version of Linux, so the forward slash is correct. But since I pipe my paths through Configuration::Path, if they need to be changed, the directory separator will be changed to the operating system’s appropriate separator.

So in my code, using the Configuration Path static method, I would do something like this.

$config = new Configuration(Configuration::Path(sprintf('conf/%s', $configFilename)));

This pathing issue alone doesn’t make your code automatically 100 percent portable. There are issues with specific PHP functions that may require different things to happen when your code is running on Windows or Linux. But the pathing issue is the easiest to do correctly.

How to Configure Apple Airport Extreme and Verizon Fios Router

I prefer Apple products over pretty much any other computer product any day of the week – if I can afford it. Prior to getting Verizon Fios, my preferred wifi router was my Apple Airport Extreme. What I like about the Airport Extreme is that I can plug a hard drive into it and do automatic Time Machine backups whenever I’m connected to my wifi network.

Here’s how my network is setup. I have two wifi networks, once provided by the Fios router and the another by my Apple Airport Extreme. The Airport Extreme connects directly to the Fios router via Ethernet.

I can not to the Airport Extreme base station. Everyone else connects to the Fios one. That limits the number of devices connecting to the Airport Extreme that has my hard drive connected to it. I don’t have to share that password with house guests. And it also splits the workload between these two routers, which really do serve different purposes in my home.

You’ll see a lot of discussion about disabling the Fios router wife network. I didn’t see why that would be necessary. If you don’t need it, it makes sense to turn it off, but I don’t think it hurts to keep it around for a guest network.

Connect Existing Eclipse Project to a Git Repository

Since we moved to Git at work for version control, I’ve had a few occasions in which I had an existing Eclipse project in my IDE that I wanted to connect with a Git repository.

The process is, I feel a bit convoluted, but it sort of made sense after I did it once.

First, I had to see the Git Repositories view. So I needed to add it. I’m on a Mac, so I went to the Window menu, selected Other and typed git in the filter box and selected Git Repositories, clicked Ok.

As an aside, if you’re looking at the Git Repositories, and you don’t see your Git repo in the list, you can add it. Just click on the Git button that has the green plus-sign. When you mouse over it, it says, “Add an existing local Git Repository to this View.”

Eclipse Git Repository View

Eclipse Git Repository View

That’s if you have a local Git repo to add, you can also clone a Git repo as well. However you get your Git repo in that view should work.

Now comes the slightly confusing part. To link up an existing Eclipse project with one of my Git repos, I did this. Right-clicked on the Eclipse project, went to Team, then Share Project, selected Git, clicked Next. Then I got a screen where I could select my Git repository.

Now that it’s all linked up, I was ready to get back to work.

For this how-to instructional to work, I’m obviously assuming you have Team and Egit installed in your Eclipse environment. How do you do that? I bet Google knows.

Convert a SoapClient Call to use curl Instead, but Return the Same Response

I have to deal with a SOAP API that doesn’t follow the the standard way of acting like a SOAP API. While 99 percent of the time, I can interact with it using the normal PHP SoapClient, but sometimes, I can’t do that and I have to revert to calling the SOAP method using curl.

It works, it just means I have to do more work than I care to do. One of the issues I dealt with today was that I didn’t want rewrite the method that was processing the SOAP response. The SoapClient returns a stdClass in whatever structure the SOAP API defined in its wsdl. With curl, I get raw XML and I needed to convert it to a stdClass. I did it like this.

$result = $this->curl($xml);
$soap = simplexml_load_string($result);
$response = $soap->children('http://schemas.xmlsoap.org/soap/envelope/')
    ->Body->children()->NameOfResponse;
return json_decode(json_encode($response));

The $response object is a SimpleXMLElement object. That’s super useful most of the time, but for, I didn’t want to rewrite the method that processes this response to use SimpleXMLElements. So that’s why I didn’t the json_encode then json_decode. The json_encode doesn’t carry with it specific class information, it’s just an “object.” So then json_decode decodes that into a stdClass, which is what my method was expected.

The $this->curl($xml) is just a method I created when I need to make a curl call instead of SoapClient call. It looks like this.

public function curl($xml, $timeout = 120)
{
    $soap = curl_init($this->_url);
    curl_setopt_array($soap, array (
        CURLOPT_CONNECTTIMEOUT => $timeout,
        CURLOPT_TIMEOUT => $timeout,
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_SSL_VERIFYPEER => FALSE,
        CURLOPT_SSL_VERIFYHOST => FALSE,
        CURLOPT_POST => TRUE
    ));

    curl_setopt_array($soap, array (
        CURLOPT_POSTFIELDS => $xml,
        CURLOPT_HTTPHEADER => array (
           'Content-Type: text/xml; charset=utf-8',
            'Content-Length: ' . strlen($xml)
        )
    ));

   $response = curl_exec($soap);
   $error = curl_error($soap);
   if (strlen($error) > 0) {
       throw new \SoapFault('SOAP-ENV:Receiver', $error);
   }
   return $response;
}

PHP Monolog Choking on Large Log Entries

I’m using Monolog to log XML coming into a SOAP service and some of the XML is really long. I’m using a LineLogParser and it’s calling preg_match to parse each line of the log. Well on the big XML files, preg_match was hitting a “backtrack” limit.

What I had to do was crank up the value for pcre.backtrack-limit until it was able to parse the log lines with large XML in them. The downside of doing this is that cranking that setting too high can crash PHP.

Another solution would be to rewrite my parser to handle these particular logs differently, but for now, this is working for me.

Linux Find Directories Consuming The Most Data

If you want to find out which directories on your Linux box that is gobbling up all of your disk space, use this command.

du -h <dir> | grep '[0-9\.]\+G'

If you want to check the current directory, don’t include a

SVN Resolving Conflicts

While I guess it’s showing its age, but subversion is still a pretty good source control tool. My problem with it is that I’m always confused about what to do when I get a conflict. This is probably because I only deal with this issue a few times a year.

Here’s what I do when I get a conflict when I’m merging or whatever.

For me there are really two options: postpone or their side of the conflict. If I select postpone, the file is marked up with the conflict. It would look something like this.

<<<<<<< .mine
// This is not speled correctly.
=======
// This is now spelled correctly.
>>>>>>> .r8390

It happened because that same line of code is modified by different checkouts of the repository. If I select their side of the conflict, the bottom code is used and I don’t have to do anything. If I select postpone, I have to go into the file, edit it with the correct code and then run “resolved” on the file (e.g. derp.php).

svn resolved derp.php

If I were to have selected my side of the conflict, the incorrectly spelled comment would be used. It depends on how you do things, but for me, it’s always their side of the conflict that works best. Postpone is if I have to think about which one is really the best code to use.

Easiest Way to Customize a Symfony Form

Before I get started, I realize that Symfony has this entire form theming apparatus and it’s great. But this is a simple technique that puts the control of the form in the hands of the person laying out the HTML rather than the developer.

All I do is when I’m rendering my form, I wrap the widget and label and errors, if applicable, in a fieldset element. I then add a class to that fieldset element.

<fieldset class="input-url">
  {{ form_label(form.myurl) }}
  {{ form_widget(form.myurl) }}
</fieldset>

This renders this HTML.

<fieldset class="input-url">
<label>Billing WSDL</label>
<input type="text" name="myurlname" required="required" value="" />
</fieldset>

That looks good to me.

Now this input element can be styled accordingly. In this instance, I just want the input text box to be longer to hold a website address. I just set the width in CSS, it’s actually SASS, but the CSS end product looks like this.

.input-url input {
    width:420px;
}

SVN Merge Changes From Branch into Trunk using Reintegration

If you’re like me, when using subversion, you have a trunk, and then you create branches for code fixes and enhancements.

But if you’re like me, you already know how to do this and so reading this is a waste of your time. But if you’re REALLY like me, you don’t remember all of these bits and pieces and you need to write it down. This is me writing it down.

Let’s pretend you have a branch located in https://svn.com/branches/JIRA-03923 that is all tested and ready to merge into the trunk, here’s how I would do it.

Grab a fresh checkout of JIRA-03923

svn co https://svn.com/branches/JIRA-03923

That creates a directory JIRA-03923.

cd JIRA-03923

Now I merge all of the changes that have happened in trunk into the branch.

svn merge https://svn.com/trunk

Commit those changes to the branch.

svn commit -m "Merged changes from trunk to this branch."

Now I grab a fresh checkout of the trunk.

cd ..
svn co https://svn.com/trunk

This creates a “trunk” directory. If you want to create a different directory provide one as a parameter like svn co https://svn.com/trunk JunkInMyTrunk. That puts all that junk your trunk.

cd trunk

Now reintegrate the changes from the branch to trunk.

svn merge --reintegrate https://svn.com/branches/JIRA-03923

Commit those changes to the trunk.

svn commit -m "Merged all changes from JIRA-03923 branch into trunk"

That branch is now useless and I remove it.

svn delete https://svn.com/branches/JIRA-03923 -m "Removing unnecessary branch"

PHP Get the First of Next Month

While having fun with dates, I needed to get the timestamp for the first of the next month, here’s how I did it with PHP.

strtotime(date('m', strtotime('+1 month')) . '/01/' . date('Y', strtotime('+1 month')));

I then used that to create a PHP DateTime object like this.

$date = new DateTime();
$date->setTimestamp(strtotime(date('m', strtotime('+1 month')) . '/01/' . date('Y', strtotime('+1 month'))));