Getting Started with PHP On Windows
Intro
For the four-or-so years that I’ve been writing code, it’s always been with a Microsoft technology; starting with VBScript, moving to VB.Net, and eventually C#, Silverlight, and WPF. I’ve been meaning to dive in to the cross-platform, open source world of Web Development, and I have explored the various aspects of it at different times, so I’m going to do an end-to-end, cross platform “Address Book” based on web technologies…HTML 5, CSS, and JavaScript for the front end, PHP for server side scripting, and MySQL for my database. However, I will still be using a Microsoft product…IIS as my web server, for the sake of familiarity. This walkthrough will help you get PHP installed on your Windows machine, and IIS configured to work with PHP.
Preparing IIS
PHP is very well documented, and I suggest you browse through the manual at http://www.php.net/manual/en/index.php to get familiar with the language before diving right in to the preparation and installation. The steps I list below are for IIS 7, on Windows Vista SP1, Windows 7, or Windows 8, and are based on the instructions in the manual I linked to above.
- Assuming you already have IIS 7 installed ( go do that, if you don’t), we need to enable FastCGI on IIS. To do this, open Control Panel, and select Programs and Features. In the column on the left side, click “Turn Windows features on or off”. In the Windows Features dialog, expand Internet Information Services, then expand World Wide Web Services, Application Development Features, and select the check box next to CGI. You should see something like this…..
- Click Ok, and Windows will do the installation.
Installing PHP
The actual process of installing PHP requires a bit of reading, because you have to set up the config file once you’ve downloaded and extracted the correct build of PHP. Here is a link to the full process… http://www.php.net/manual/en/install.windows.manual.php . Once you download and extract PHP, and get your config file set up, we’ll need to tell IIS how to process PHP requests.
Configuring IIS to Process PHP
These last steps will guide you through using the IIS Manager UI to create a handler mapping for PHP, and, again are based on the steps in http://www.php.net/manual/en/install.windows.iis7.php . I recommend you take a look at their manual after doing this simple UI setup, as they have detailed information on how to use the command line tool, and information about impersonation and file system access.
- Open Control Panel, select Administrative Tools, and double click IIS Manager.
- Select the Server node in the tree view on the left side, and then double click the Handler Mappings icon in the IIS section of the Features View. It should look similar to this…
- In the Actions pane on the right, click “Add Module Mapping…”
- Enter the following information in the “Add Module Mapping” dialog…
- Request path: *.php
- Module: FastCgiModule
- Executable: C:\[Path to PHP installation]\php-cgi.exe
- Name: PHP_via_FastCGI
5. Click “Request Restrictions” button and then configure the mapping to invoke handler only if request is mapped to a file or a folder;
6. Click OK on all the dialogs to save the configuration.
Test
If everything went according to plan, your default website is now configured to process PHP requests. Here’s how we test it…
- Open up Notepad and enter the following line of text, without the quotation marks surrounding it…”<?php echo ‘Hello World’; ?> “
- Click File, Save As…, and save the file as Test.php ( be sure to set the file type to All Files) in your My Documents folder.
- Copy the Test.php file to C:\inetpub\wwwroot.
- Finally, open a web browser and browse to localhost/test.php. You should see your Hello World output.
Conclusion / Now What?
This walkthrough covered the very basics of getting PHP installed, and setting up IIS to process PHP requests. It didn’t begin to touch on the actual language, syntax, or usage of PHP, but there is great documentation and plenty of walkthroughs at php.net to get you started on using PHP. My next blogs will be about setting up MySQL ( Spoiler: it was infinitely easier than my first attempts at installing and configuring Microsoft SQL Server ) and connecting to it from PHP, and how to use browser detection to detect mobile devices and load appropriate css sheets.
ContentControl “bug” in WinRT
Background
I was recently on a WinRT project that required showing a hierarchy of assets that the user could browse through, ultimately leading to an “asset details” view where they can interact with the selected asset. One of the interactive features was to have a toggle button that would hide/show a details pane with the asset description. Throughout the asset hierarchy, the data templates would bind to Name and ImageUri properties on the assets to display them. When I got down to the asset details level, I needed to wrap the asset in a ViewModel to support the command that I needed to implement the description toggle.
Implementation
After messing around with the built in Transition API trying to get my description pane to animate in, I realized that I needed to expose a separate Asset property on my VM so my description pane could bind to it via a ContentControl with a ContentThemeTransition, and to do the toggling I would just null the object in the VM and let the Transition work its magic. I tested this without the ContentTemplate set on the ContentControl (just bound directly to the extra Asset property I added to my VM), and it worked as I expected…..the description pane was hidden, and when i clicked the toggle button the pane animated in and showed that it was bound to an Asset object.
Problem
The problem started when I added the DataTemplate that was bound to the ImageUri and Name of that Asset property. When I tested it, the description pane was instantly visible before I clicked the toggle button.
Solution
After a lot of breakpoints and head scratching, my theory was that, even though the Content property of the ContentControl was bound to this seperate Asset that I added to the VM, it still looked up the tree to find those properties when the object was null. Since the VM itself had those same properties, the DataTemplate was binding to that and displaying the pane when it shouldn’t have been. Sure enough, I made a separate little class to hold the Name and Description properties, and named them differently, and it worked fine. The surprise for me here was that the ContentControl was looking up the tree for property binding when it’s content was null, and it only did it when a DataTemplate was defined. I’m not sure if this is a bug, or by design, but it can cause a headache if you’re not expecting it.
Automatic UI Transitions in Windows Store apps
Basics
When you’re making apps intended for modern touch hardware, it’s important that your UI feels alive, fluid, and in motion. Some of Microsoft’s XAML controls will give you this motion for free, like Panorama in Windows Phone and the FlipView in WinRT, but other than that it was very difficult to duplicate the built-in animations and transitions of those respective platforms. The WinRT platform introduces the Transition API that applies to Controls and Containers that can apply a built in animation in a response to a predetermined trigger. Transitions are applied to individual controls using the Transitions property, and to Panels using the ChildrenTransitions property. For example, adding an EntranceThemeTransition to the ChildrenTransitions collection of a Grid will cause all children of the Grid to automatically slide in from the right when they first appear. Getting the default subtle slide in from the right is this simple…….
Adding Transitions via Designer Instead of XAML
Back when Visual Studio and Blend both served completely different purposes, I always preferred doing UI related in Blend so that I can see all the Properties right in front of me and set them visually. In Visual Studio 2012, a lot of that ability to see and set Properties visually was added from Blend, and it makes setting and customizing Transitions very simple. Here’s how…
First
If you don’t already have the Document Outline and Properties Window visible ( they usually aren’t ), go up to View, click Properties Window, then go back to View, Other Windows, Document Outline. Here’s what mine looks like…
Next
All we need need to do is select the Grid in the document and, in the Properties window on the right, click the small ellipse button next to the ChildrenTransitions. You should see a new dialog window to add ChildrenTransitions with a DropDown at the bottom. Select EntranceThemeTransition and click Add. You should see the following window, which will allow you to configure the Transition properties. You should see this window if you’re in the right place….
Conclusion
The new Transitions API is an easy, flexible way to add predefined system animations to your UI. I’ve barely scratched the surface of what can be done with this system, but I will be using them where appropriate and will make more posts when I figure out some of the more advanced features.
Easy Pinch-to-zoom in WinRT
On a recent project, I was tasked with adding pinch-to-zoom for images that would be displayed in a WinRT app. Since this feature doesn’t come for free I started thinking of ways to handle the gesture input and apply the appropriate amount of scaling while still playing by the rules of MVVM. Much to my delight, I soon discovered that the ScrollViewer can handle this sort of thing be default. For the purpose of scaling an image, you’ll want to disable the Vertical and Horizontal scroll bars, and use an Image control as the content of the Scroll Viewer. The key properties on the ScrollViewer you’ll want to use to control the zoom level are MinZoomFactor and MaxZoomFactor. The defaults are 0.1 and 10, respectively, but in my case I needed to set the MaxZoom based on the resolution of the image itself. There are a number of ways to do this, and my solution uses a custom control for it. Here’s what the logic for that looks like in my control…….
This is the handler for the Opened event of the Image control. The Source property you see on the first line is a Dependency Property I exposed on this custom control to expose the Image Source property. The first if statement checks to see if the image is smaller than the screen in both directions, in which case I display the image at native size with no scaling. The next block handles images that are larger than the screen in either or both directions. In that case, I divide the bitmap pixel width and pixel height by the actual rendered width and height of the ScrollViewer and use the larger value as the MaxZoomFactor. The end result is that the image is scalable up to it’s native size. Here’s what the xaml of my default control template looks like…..
And that’s all there is to it! If you don’t want / need to go down the custom control path, you can very easily just use the ScrollViewer and Image controls and set the zoom values directly in Xaml or data bind them. Either way is much easier than handling the gestures and scaling manually.
Fluid Move Set Tag Behavior In a Master/Detail View
The FluidMoveSetTagBahvior is a helpful, but scarcely documented, feature that allows you to apply fluid movement between UI elements that share both a visual relationship as well as a data relationship. The most common example of this would be the Master/Details view where you have a list that displays all available items, and a view that displays the details of the selected item. By using the FluidMoveSetTagBehavior and FluidMoveBehavior in Expression Blend, we can make the selected item appear to “fly out” of the list and into the details view.
Here’s how…
In Expression Blend, search for FluidMove (not case sensitive) in the asset panel. Next, drill down into the ItemsTemplate of whatever control you’re using to display your Master list ( standard ListBox in my example). Now, you’ll need to drag that FluidMoveSetTagBehavior from the asset panel down to the UI element in the ItemsTemplate where you want the “fly out” animation to begin. It my example, I applied it to the root container (the StackPanel). Here’s how that looks in Blend…
Next, click the FluidMoveSetTagBehavior that you just dropped, and turn your attention to the Properties panel on the right. The key here is to set the Tag property to DataContext. What this does is register the DataContext object ( in my example, a Person object) to a hidden data store that our corresponding FluidMoveBehavior will use later to execute the animation.
Next, we’ll apply the FluidMoveBehavior to the Details view to enable the “fly out” animation. In the Objects and Timeline panel in Blend, select the UI element in your Details view that will be the end point of the animation. In my example, that’s the root StackPanel of my Details view. Drag the FluidMoveBehavior ( NOT the FluidMoveSetTagBehavior ) down to this UI Element. Here’s how that looks in my sample…
Once again, we need to select the FluidMoveBehavior we just added and go over to the Properties panel on the right. Set the InitialTag property to DataContext. Now, when the DataContext of this UI element changes, the FluidMoveBehavior will check the hidden data store for the last known location of this new DataContext object, which would be the last location of the original StackPanel where we set the FluidMoveSetTagBehavior. Now that we have the FluidMoveBehavior wired up, we need to connect the DataContext of the Details StackPanel to to SelectedItem of the Master ListBox. When the SelectedItem changes, the DataContext of the StackPanel also changes, and triggers the FluidMoveBehavior. If you’re using the MVVM pattern ( which my sample is), you’ll want to do the following….
On your Master ListBox, bind the SelectedItem to the corresponding property on your ViewModel, and set it as a Two-Way binding. Here’s how mine looks…
Now, bind the target UI element in your Details view to that same property that you just bound the ListBox SelectedItem to.
and……voila!… Fluid Move Demo
Multi-app support on a single Windows Phone 7 push notifications server
Windows Phone 7 push notifications are tricky. Take Microsoft’s clear-as-mudd “overview” diagram, for example…
All sorts of colors and arrows going on there. The green parts represent code that you write, and the blue parts represent what Microsoft already has in place. The numbers and arrows represent the awkward dance between them. I’ll try to explain…
First, in your application (green side of step 1) you have to use Microsoft’s client side portion of their Push Notification Service, which is the HTTPNotificationChannel class (blue side of step 1) , to see if the app already has an open notification channel with Microsoft’s service (that’s the MPNS box in the bottom right). Only one channel per application is allowed, and you can use that single channel for all of your apps Push Notification needs.
If there is no channel open already, you can go ahead and use the aforementioned HTTPNotificationChannel class to set one up. This is step 2 in the diagram above, and here is a sample of it in code….
*I used this tutorial by Ben Cull for most of the code you’re going to see, until we get to the “multi-app” support on the server.
private void RegisterDevice() { HttpNotificationChannel httpChannel; httpChannel = HttpNotificationChannel.Find("TestChannel"); if (httpChannel != null) { SubscribeToChannelEvents(); SubscribeToService(); } else { httpChannel = new HttpNotificationChannel("TestChannel", "TestService"); SubscribeToChannelEvents(); httpChannel.Open(); if (!httpChannel.IsShellToastBound) { httpChannel.BindToShellToast(); } if (!httpChannel.IsShellTileBound) { var c = new System.Collections.ObjectModel.Collection<Uri>(); c.Add(new Uri("http://0.tqn.com/")); httpChannel.BindToShellTile(c); } } }
The call to the “SubscribeToChannelEvents()” method above is represented by step 3 in the diagram, and here’s what it looks like in code…
private void SubscribeToChannelEvents() { httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(httpChannel_ChannelUriUpdated); httpChannel.HttpNotificationReceived += new EventHandler<HttpNotificationEventArgs>(httpChannel_HttpNotificationReceived); httpChannel.ShellToastNotificationReceived += new EventHandler<NotificationEventArgs>(httpChannel_ShellToastNotificationReceived); httpChannel.ErrorOccurred += new EventHandler<NotificationChannelErrorEventArgs>(httpChannel_ErrorOccurred); }
Step 4 in the diagram is sending your notification channel’s URI (it gets this URI through magic during step 2). This is where you need to have a WCF REST Service set up with a database to hold your device id’s and URI’s. The code below shows how to subscribe to the service from the client side, but if you want the server side setup and registration you can find all of that in Ben Cull’s blog post here
public string ParseANID(string anid) { if (!String.IsNullOrEmpty(anid)) { string[] parts = anid.Split('&'); IEnumerable<string[]> pairs = parts.Select(part => part.Split('=')); string id = pairs.Where(pair => pair.Length == 2 && pair[0] == "A").Select(pair => pair[1]).FirstOrDefault(); return id; } return String.Empty; } private void SubscribeToService() { if (!NetworkInterface.GetIsNetworkAvailable()) { return; } string id = ParseANID(UserExtendedProperties.GetValue("ANID") as string); var emulatorUrl = string.Format("http://localhost:55875/notifications/register?deviceid={0}&uri={1}", id, httpChannel.ChannelUri.ToString()); var wc = new WebClient(); wc.DownloadStringCompleted += new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted); wc.DownloadStringAsync(new Uri(emulatorUrl)); }
The “ANID” that you see above is pretty much a unique guid generated for each user’s Live ID. Also, the emulatorUrl variable above is assuming that you’re running the WCF service on the same machine that you’re writing the client side phone code on, and that you’re using the phone emulator to debug. If you’re using an actual device to debug than “localhost” will produce nothing but disappointment, so adjust your url as needed. At this point, if you followed the WCF REST Service tutorial i linked to above, you’ll have the infrastructure in place to send push notifications, but no actual way of doing so yet.
For that we’ll need a service running on the server, with a timer that goes out and determines if there’s any updates it needs to send to anyone (for example, a weather service that checks for severe weather wvery 30 minutes based on a zip code sent by the client side phone app). But all of this is for a single app. If I wanted to do push notifications again in the future i would have to do this all over again for each new app. Instead, I decided to use a single REST Service, web service, and central device database. The service doesn’t contain the timer with the application logic. Instead, each app that you want to support is represented by a class that you instantiate in the OnStart() method of the service, and each app class contains its own timer, logic, and its own database with device id’s and any parameters required for it to work. For the sake of simplicity below are 2 examples of test apps that use the AppName property of the central database rather than their own seperate databases….
namespace PushNotificationService.Apps { public class TestApp { private WP7AppDBEntities _dbContext; private readonly string _appName = "TestApp"; public TestApp() { _dbContext = new WP7AppDBEntities(); var t = new Timer(); t.Interval = 10000; t.Elapsed += new ElapsedEventHandler(OnTimerElapsed); t.Start(); } private void OnTimerElapsed(object sender, ElapsedEventArgs e) { _dbContext.Devices.Where(d => d.AppName == _appName).ToList().ForEach(d => { try { PushNotifications.SendToast(d.URI, "Test", "Hello"); } catch{} }); } } }
namespace PushNotificationService.Apps { public class TestApp2 { private WP7AppDBEntities _dbContext; private readonly string _appName = "TestApp2"; public TestApp2() { _dbContext = new WP7AppDBEntities(); var t = new Timer(); t.Interval = 20000; t.Elapsed += new ElapsedEventHandler(OnTimerElapsed); t.Start(); } private void OnTimerElapsed(object sender, ElapsedEventArgs e) { _dbContext.Devices.Where(d => d.AppName == _appName).ToList().ForEach(d => { try { PushNotifications.SendToast(d.URI, "TestApp2!", "It's working!"); } catch{} }); } } }
The PushNotifications.SendToast method that you see above represents step 5 of the diagram, and is provided in detail here.
And here are the classes being instantiated in the OnStart() method of the service…
protected override void OnStart(string[] args) { var testApp = new TestApp(); var testApp2 = new TestApp2(); }
Push Notifications on Windows Phone 7.
While the MSDN has plenty of documentation on what Windows Phone 7 Push Notifications are, what they do, and how they work, they didn’t have much in terms of how to set up a web service for Push Notifications. I found an awesome tutorial here…http://benjii.me/2011/01/push-notifications-in-windows-phone-7-2-code-on-the-server/. It’s a 3 part series that shows everything from building your web service, registering your phone with the web service, and sending push notifications to Microsoft’s Push Notification system from your web service. The only thing missing from the posts is the few lines of code needed to enable the usage of web images as background tiles. Here’s that block of code….
if (!httpChannel.IsShellTileBound) { var c = new System.Collections.ObjectModel.Collection<Uri>(); c.Add(newUri("http://0.tqn.com/")); httpChannel.BindToShellTile(c); }
To enable external images, create a collection of Uri’s and add each domain that will be hosting an external image that you want to use (domain names are limited to 256 characters). Then, pass the collection to the BindToShellTile method on your http channel. The server side code for updating the tile is in part 3 of the blog post mentioned above.
Beginning CSS
The latest project that I’m working on here at IK requires quite a bit of CSS. The issue with that was that I’ve never used CSS before in my life. Like anyone else faced with learning a new technology in a relatively short period of time, I found myself asking “Where do I begin?”. Luckily it didn’t take long to find my starting point, so while I’m not yet making ultra fancy websites I can recommend the following website to anyone searching for a good entry point into CSS….. http://www.w3schools.com/css/default.asp. A couple hours of these tutorials and you’ll know enough CSS to be dangerous. Enjoy!