Showing posts with label php. Show all posts
Showing posts with label php. Show all posts

Add a Group-By Scope to Yii's CActiveRecord Subclass

Yii Framework allows for named scopes to be added to a CActiveRecord's subclass (you can read more about this here). This also makes it more convenient to filter models based on a predetermined criteria. You can chain them with any filter methods of that class, and ultimately the CDbCriteria methods like `findAll()`.

To site an example, let's have a database table named `animals`. It also has the following fields: id, name, and classification. Let's fill this up with some data. I know this can still be normalized, but let's just leave it like this for the sake of simplicity.

[ 1, 'Eagle',     'Bird']
[ 2, 'Peacock',   'Bird']
[ 3, 'Kangaroo',  'Mammal']
[ 4, 'Dog',       'Mammal']
[ 5, 'Horse',     'Mammal']
[ 6, 'Snake',     'Reptile']
[ 7, 'Turtle',    'Reptile']
[ 8, 'Lizard',    'Reptile']
[ 9, 'Crocodile', 'Reptile']
[10, 'Spider',    'Arthropods']

Now, assuming we're asked to provide a summary of classifications, like return a list of classifications with a number of animals in each of them. This is how our sql query looks like if nothing else is added in the criteria.

SELECT t.classification, COUNT(*) AS animalCount
  FROM `animals` AS t
  GROUP BY t.classification
  ORDER BY animalCount DESC;

If you try to run this query, the result looks something like this.

[Reptile,     4]
[Mammal,      3]
[Bird,        2]
[Arthropods,  1]

Let's assume that we've created a model class named `Animal`, which represents our `animals` db table and has the following method which does the same thing as the aforementioned sql query. It looks like the following:

public function scopes()
{
  return array(
    'groupByClass' => array(
      'group'   => 't.classification',
      'select'  => 't.classification, COUNT(*) as animalCount',
      'order'   => 'animalCount DESC',
    ),
  );
}

This is the overriden method coming from CActiveRecord. To use this, we simply type:

Animal::method()->groupByClass()->findAll();

Then we get the same result:

[Reptile,     4]
[Mammal,      3]
[Bird,        2]
[Arthropods,  1]

You must be wondering how the heck I'm supposed to access `animalCount` alias. Well for that, we can simply add a special property. That would of course be of the same name, which is `animalCount`.

So there you have it.

Facebook IFrame App in Safari

You don't really need cookies to make your Facebook IFrame app work in Safari browser. I remember two years ago, to make Page Tab applications work in Safari, you only need to make use of this trick. I won't be explaining it in details here.

Just recently, I was asked to do this new Fb project that's intended for Page Tab, which now is an iFrame-only platform. I've been developing it using Chrome browser. And when I finally get to test it on Safari, unsurprisingly, it's the same old scenario. What's worse is that the old trick won't work anymore (you better read this).

This app relies so much on Javascript. And instead of deploying several php pages, I only need to come up with a startup page which when loaded on the iFrame, loads the rest of the required scripts. Other pages are dynamically constructed using html fragments that are parsed by a templating script. So most of the Client-Server transactions are done asynchronously. And with Safari continously blocking third-party cookies, it just doesn't work.

After hours of googling for answers, I turned to Facebook's PHP SDK. I found out that it doesn't really require you to use cookies after all (now at 3.1.1). If you take a look at `BaseFacebook` class, particularly the `getSignedRequest` method, you'll see that it first checks the request parameter for Signed Request data (they used to have `session` before this).

...
public function getSignedRequest() {
  if (!$this->signedRequest) {
    if (isset($_REQUEST['signed_request'])) {
      $this->signedRequest = $this->parseSignedRequest(
        $_REQUEST['signed_request']);
    } else if (isset($_COOKIE[$this->getSignedRequestCookieName()])) {
      $this->signedRequest = $this->parseSignedRequest(
        $_COOKIE[$this->getSignedRequestCookieName()]);
    }
  }
  return $this->signedRequest;
}
...

With this in mind, it's possible to send `signed_request` data along with an Ajax request which the PHP SDK can use to determine the user and for your app to verify as well. I use FB.getLoginStatus to acquire a copy of this data. This of course assumes that the user has already authorized your app. Otherwise you'll have to let him do so.

The following example uses jQuery's `$.ajax`.

...
$.ajax({
  url: BACKEND_LINK_HERE,
  type: 'POST',
  data: {
    signed_request: 'sOm3ReA||yLo0ooooooo...oooooooooNgT3xtHeR3',
    another_data: 12345
  }
})
...

So that's it. You need to make sure you have a valid `signed_request` data each time a user interacts with your application. Don't even think about storing it because the access token contained will soon expire which then deems it useless (about 2.5 hours from the moment the user interacted with your app). Yes that's right. And just to let you know, `offline_access` is no longer supported.

Here's a Facebook article about handling invalid and expired access tokens in case you're interested.


Related posts:

Facebook iOS: Use Access Token in PHP

Yes that's right. As of the time of this writing, it is possible to use the user granted access_token back in some server side scripting language like PHP. If you currently have a 255 varchar field size for access_tokens in your database, you may want to bump that up a bit.

The time I made the sample code ran and allowed me to log in (one that came bundled with the Facebook iOS SDK from GitHub), I began realizing that the token quite have different format than the one we usually see in web-based apps (e.g. FB iFrame app).

The usual token looks something like this:

213455681425|1.BGgrgnfWrdpG_X18.3600.1213252135.2-1334679|dHcDbxGbeYbLg3SRgw12fdf4gd60

..while in mobile:

v9ylvkttPnuFWUX4KVdjDPB0SRXkuKX7z281rqjHuG0.eyJpdiI6ImEwWXBDaEtncWpDTU5ibUNuQWdROWcifQ.Y-DwxRY2ZAFZiP7EVuR-HksXqmGw9LXP6umGrfz2XnjSLm0a508u7_jXq0_Kz5a2S8AUUulzUvIRVxTS51_i6VfSByOCbFBIKoBe0-n-Pa8NC29wbuVmGJLvq4W-ezhv0DzA3diiCIqCybt9ELDXoA

The plan was, allow users to connect to our application using FB. Then once he approved it, we take a copy of the access_token and save it back to the server. Same access_token will be used once he logs in to his account using our web-based app.

Well, so far so good. Let me know if yours doesn't work.


Related posts:

Facebook `comments.remove` API Method

With FB's Comment Social plugin, having to remove comments on a certain Application is a click away as long as the current user has the Admin rights. This thing right here may be necessary to those who wanted a custom Administration sort of utility for managing FB App related comments.

Here's a sample code of how one could implement this method:

Grab the Picture of a Facebook Graph Object

Here's what you need to do to get to the actual location of a Facebook profile picture using PHP cURL (this comes in handy if you plan to store the picture somewhere else). In particular, we can grab the pictures of People, Events, Groups, Pages, Applications, and Photo Albums (these are called objects in Graph API).

Convert text URLs or Hyperlinks to clickable links

Here's a PHP code that can parse text URLs or Hyperlinks into a clickable link. This is useful when displaying text contents with inline links written along.

Tips on Developing Silverstripe Applications

Here's a handful of tips dedicated to all Silverstripe CMS developers out there (because I myself develop SilverStripe applications too).

Tips on Upgrading to Silverstripe CMS version 2.4

I just switched to Silverstripe 2.4+ and came accross several changes in contrast with SS2.3+. I'm gonna list here few of those changes so you guys will be aware of them. And I pledge to update this from time to time. Hopefully, this will guide you when you finally decide to upgrade your old version. Or this might as well motivate you to upgrade like me.

Drupal 6: Custom Online Members Block

With the help of some PHP codes, showing a block that contains a list of your site's online members can be achieved (with a left floating picture beside each member name). The code was adopted from the Drupal 6 core, User Module. We all know that there is already a bundled block for this with Block name Who's-Online. But if you really want to do more about it, like adding a user picture, then you can do so with Blocks (I'm pretty sure you can do this with Views as well). And don't forget to enable PHP-Filter module. This can be found at admin/build/modules/list under Core-Optional modules. Then select PHP Code option among the list of Input Formats available when creating the new block.

How To Increase PHP Session Timeout

This thing got me into trouble few months ago. Few of my teammates keep getting stumbled on the same obstacle. And this is what I keep advising them. That you need something fixed when your PHP Session expires in such a short period of time over a shared hosting server environment.

Embedding HTML Forms within another HTML Form

I haven't googled much on the topic "Embedding HTML Forms within another HTML Form". Although if there is any possibility that Forms can be nested, well I doubt if that would be a nice idea. I came up with one possible solution to this because one of the projects I recently handled requires that the application keeps its basic functionalities even if the Browsers' Javascript is turned off. I guess you guys should really consider the fact that some of the users visiting your site have their Javascript turned off for security reasons. And by that, your site should still work as expected. They may be less than what you might have anticipated but think about the idea that they might end up visiting and purchasing goods in your competitors' website instead. Now how's that?

How to get Visitor's IP Address using PHP

Getting the IP address of your Visitor is possible using PHP. Finding the IP address is very important requirement for many scripts where we store the members or visitors details. For security reasons we can store IP address of our visitors who are doing any purchases or recording the geographical location. Sometimes, basing on a particular IP address, we can redirect the browser to different areas of the site. There are many applications using this actually.

Magento vertical menu for product categories

Here's something about creating a vertical menu for Magento product categories. Ok. As a beginner in Magento theming, it took me quite a couple of days just to catch the right solution for what was required in my previous project - a theme with its custom homepage having vertically positioned menu. I kept googling that time and luckily found this very helpful wiki in Magento community. Here's a link to that. If you're interested, you really need to read it.

Can't Login to Magento Admin Panel after successful Installation

Here's a simple solution to those facing Fresh Magento Installation Backend login problem. It's obviously an issue around Cookie settings. So let's get to it.

How to test or check if MOD_REWRITE is enabled

Some of you might have tried hiding your index.php from your site's URL and nothing did work (say you have http://domain.com/index.php/about_us) .

Well not anymore . I once had this sort of thing too and luckily found a solution from the net.