Tag Archives: fail

Integrating calculated fields and model data in CakePHP

(This is mostly a summary of Dealing with calculated fields in CakePHP’s find().)

One of the great things about CakePHP is that if it doesn’t have some core functionality you want/need there are easy ways to add it. More and more I’m taking advantage of this ability. This all comes about because I wanted to have calculated fields available inline with the model data. By calculated fields I mean results that are not data columns (e.g. SELECT *, CURDATE() AS current_date FROM users … yes, that’s a fairly contrived example).

By default Cake places results from calculated fields outside the model data, like this:

Array
(
    [0] => Array
        (
            [User] => Array
                (
                    [id] => 1
                    [username] => aaas
                )

            [0] => Array
                (
                    [current_date] => '2011-05-13'
                )

        )
)

What we want is to place the “current_date” calculated field inside the User model, so it’s more naturally accessed with $users[0]['User']['current_date'] instead of $users[0]['User'][0]['current_date']. Easy enough to do through a model’s afterFind() callback method (to make it widely available place the function in app_model.php).

function afterFind($results, $primary=false) {
	if($primary == true) {
		if(Set::check($results, '0.0') && Set::check($results, "0." . $this->alias)) {
			$fields = array_keys( $results[0][0] );
			foreach($results as $key=>$value) {
				foreach( $fields as $fieldName ) {
					$results[$key][$this->alias][$fieldName] = $value[0][$fieldName];
				}
				unset($results[$key][0]);
			}
		}
	}
	return $results;
}

And yet, even as I add such enhanced functionality to my web apps I’m finding limits. The above logic is complicated a little because you don’t know what type of results you’re getting. The results you get from calling, for example, find('all') versus find('count') are not the same. But Cake doesn’t give any hints to the afterFind() callback, and as a result additional logic is included to try and guess at our data structure. The above adds a quick but incomplete hack by a) checking that the results are for the primary model queried (e.g. not from contained model), b) checking for the presence of nested numerical keys, and c) checking that there is model data to integrate with.

The take away is that while the code produces the desired data structure, in its current form it does so only for specific results.

Executable blocking on Windows 2003

I was recently attempting to install PHP using an installer (MSI) I downloaded to my local workstation and copied to one of our servers. When I attempted to run the installer I received the following inscrutable warning:

Windows cannot access the specific device, path, or file. You may not have the appropriate permissions to access the item.

Thanks, Windows, that’s helpful. I had no idea what was happening, especially since I was logged in as an administrator with full control of the file.

As usual, the web was my friend in solving the problem. Windows 2003 Server has a security feature where executables copied from remote systems are blocked for execution unless allowed by an administrator. The feature appears to have been present for a while (since SP2?), but I don’t recall running into it before. As mentioned above, the file in my case was copied from my workstation over SMB; I don’t know if other transfer methods are also affected. I don’t have a problem with the feature, but I do have a problem with how it’s implemented. An indication in the pop-up of why the file could not be accessed would have resulted in a resolution of seconds not … er … minutes.

The resolution is simple enough, go into the properties for the file and you’ll see at the bottom a security warning and a button that allows you to unblock the file.

Click the “Unblock” button and you can execute the file as you normally would.

References:

Careful with Google Analytics filters

I made a change to the filters attached to our profiles in Google Analytics (GA) so that we would capture only relevant traffic. Namely, I was attempting to avoid capturing traffic to our development servers. Unfortunately, instead of a domain-based filter I created one that resulted in GA capturing zero traffic. Fail.

The problem stems from my attempt to use a predefined filter to block out the unwanted traffic. I tried to set up a “include only traffic from the domains that include” filter, thinking this was a filter on the server’s domain. What this filter actually checks against is the visitor’s domain. I guess a little more attention to the “from/to” part of the filter would have made this apparent, but Google doesn’t provide much documentation (or even better, examples) on their filters.

After a few days I noticed the sudden lack of data and realized my error. Turns out what I really wanted was a custom filter with the following settings:

  • filter type: include
  • fiter field: hostname
  • filter pattern: regex for the domain (e.g. www.project2061.org
  • case sensitive: no

Even after looking at this again, it’s still not clear to me why these two are different. The descriptive language is almost identical. Google needs to do some work here.

Of course, there are also other solutions to this problem, listed below:

  • Use an include to pull in the GA code and only populate the file on the servers where tracking should occur. The only significant problem here would be forgetting to set up the include.
  • Create advanced segments in GA that filters out traffic to anything other than the production domains. This would have the benefit of being able to track both production and development server use in the same report. But if there are any significant difference between the two sites then this wouldn’t be all that helpful.

References: