Sunday, April 21, 2013

YII session control

{Write}
Yii::app()->session['url']='http://pritomkumar.blogspot.com';
Yii::app()->session->add('author','Pritom Kumar');
 
{Read}
echo Yii::app()->session['url']; //http://pritomkumar.blogspot.com
echo Yii::app()->session->get('author'); // Pritom Kumar

YII set and get flush message

In controller: 
Yii::app()->user->setFlash(
    'Message00', //a string for key usage
    'This is msg from controller.'
);
 
In view: 
if(Yii::app()->user->hasFlash('Message00')){
    echo '<div class="flash-success">';
    echo Yii::app()->user->getFlash('Message00');
    echo '</div>'; 
}

Sorting with Set::sort() in CakePHP 1.2

Sorting data returned from a database query

You're probably thinking "Err... idiot... just use the ORDER BY functionality in the model!". Yeah, we could do that, but that's not much fun!
Here is my freshly baked People controller, which gracefully passes some data to my view. Nothing special here.

<?php
class PeopleController extends AppController {

    var $name = 'People';
    
    function index() {
        $this->set('people', $this->Person->find('all'));
    }
    
}
?>
 
The $people array is in the standard format we receive from our model, and has a belongsTo association (Occupation).
Array
(
    [0] => Array
        (
            [Person] => Array
                (
                    [id] => 1
                    [occupation_id] => 2
                    [name] => Harry Potter
                    [birth_date] => 1980-07-31
                )

            [Occupation] => Array
                (
                    [id] => 2
                    [name] => Student
                )

        )

    [1] => Array
        (
            [Person] => Array
                (
                    [id] => 2
                    [occupation_id] => 1
                    [name] => Albus Dumbledore
                    [birth_date] => 1881-08-01
                )

            [Occupation] => Array
                (
                    [id] => 1
                    [name] => Headmaster
                )

        )

    [2] => Array
        (
            [Person] => Array
                (
                    [id] => 3
                    [occupation_id] => 3
                    [name] => Severus Snape
                    [birth_date] => 1959-01-09
                )

            [Occupation] => Array
                (
                    [id] => 3
                    [name] => Professor
                )

        )

)

Default order

Instead of dumping the entire contents of the $people array after each Set::sort() call, I will present the data in a pretty table.
Person.id Person.name Person.birth_date Occupation.id Occupation.name
1 Harry Potter 1980-07-31 2 Student
2 Albus Dumbledore 1881-08-01 1 Headmaster
3 Severus Snape 1959-01-09 3 Professor

Person.birth_date DESC

Set::sort() currently takes 3 arguments - the array to sort, the array value to sort on, and the sort order. As with the other Set methods, we specify the value to sort on using a key path. This makes it super easy to deal with complex arrays.

$people = Set::sort($people, '{n}.Person.birth_date', 'desc');
 

Person.id Person.name Person.birth_date Occupation.id Occupation.name
1 Harry Potter 1980-07-31 2 Student
3 Severus Snape 1959-01-09 3 Professor
2 Albus Dumbledore 1881-08-01 1 Headmaster

Occupation.name ASC

It's just as simple sorting on a value of an associated model, in this case the person's occupation. Unfortunately the sort method doesn't current have a default sort order, so we need to specify this. We can also use the PHP constants, SORT_ASC and SORT_DESC.

$people = Set::sort($people, '{n}.Occupation.name', SORT_ASC);
 

Person.id Person.name Person.birth_date Occupation.id Occupation.name
2 Albus Dumbledore 1881-08-01 1 Headmaster
3 Severus Snape 1959-01-09 3 Professor
1 Harry Potter 1980-07-31 2 Student

Saturday, April 20, 2013

YII model with some action perform

Add custom error to a model:
$model->addError('email', 'No valid account associated with this email address.');

Validate a model:
$model->validate();

Yii model without table

<?php
class RegistrationForm extends CFormModel
{
    public $email;
    public $password;
    public $repassword;
    public $displayname;
    public $verifycode;


    public function rules()
    {
        return array(
            array('email, password, repassword', 'required'),
            array('password, repassword', 'length', 'min'=>4),
            array('email, password, repassword, displayname', 'length', 'max'=>200),
            array('email', 'unique'),
            array('repassword', 'compare', 'compareAttribute'=>'password'),
            array('email', 'email'),
            array('verifycode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements()),
        );
    }
    
    
    public function attributeLabels()
    {
        return array(
            'email'=>'Email',
            'password'=>'Password',
            'repassword'=>'Re-Password',
            'displayname'=>'Display Name',
            'verifycode'=>'Confirm you are not alien',
        );
    }
           
}

Yii create a new model with common attributes

The rules() method, like most of the Yii methods, returns an array of data:
public function rules()
{
    return array(/* actual rules */);
}
The first, most obvious, restriction is to indicate that a field is required. Just use a comma-separated string of field names as the first returned value and the word required as the second:
array('name, email, subject, body', 'required'),
You can also specify that a value must be a number or, more specifically, an integer. This syntax is slightly different. Here, I indicate that the ext field must be an integer:
array('ext', 'numerical', 'integerOnly'=>true),
For strings, you can restrict the length to a maximum value:
array('name','length','max'=>40),
Or a minimum value:
array('name','length','min'=>6),
Or both:
array('name','length','min'=>6, 'max'=>40),
Another useful validation routine is to check that a string is an email address. I do that here, to a userEmail field:
array('userEmail', 'email'),
To indicate that a string needs to be a URL, use:
array('link', 'url'),
Another useful rule is for comparisons, like when a user registers and you have to make sure that the confirmed password matches the password:
array('password1', 'compare', 'compareAttribute'=>'password2', 'on'=>'register'),
There is also the “safe” rule. This rule is used to provide access to data that isn’t otherwise validated. For example, an email address is already considered to be “safe” because it must abide by the email rule, but the Employee Model has the leaveDate field which won’t have any rules applied to it (in part, because there are no date-specific rules and also because the field can be null). To be able to refer to that value, it must be declared as safe:
array('leaveDate', 'safe'),
If there are multiple fields to make safe, just separate them with commas.
There’s also a rule to indicate which fields should be safe to search on. By default, every rule is made safe in a search, but you may want to change that behavior by removing fields from the list:
array('id, departmentId, firstName, lastName, email, ext, hireDate, leaveDate', 'safe', 'on'=>'search'),
So, using this information, the complete rules() method for my Employee Model is:
public function rules()
{
    return array(
        array('departmentId, firstName, lastName, email, hireDate', 'required'),
        array('departmentId, ext', 'numerical', 'integerOnly'=>true),
        array('firstName', 'length', 'max'=>20),
        array('lastName', 'length', 'max'=>40),
        array('email', 'length', 'max'=>60),
        array('email', 'email'),
        array('leaveDate', 'safe'),
        array('id, departmentId, firstName, lastName, email, ext, hireDate, leaveDate', 'safe', 'on'=>'search'),
 );
}
Moving on, another key Model method is relations(), which indicates the relationship between Models. If your database is designed properly, this method will already be properly filled out, again thanks to Gii. Here’s how the relations() method in the Employee Model looks:
public function relations()
{
    return array( 
        'department' => array(self::BELONGS_TO, 'Department', 'departmentId'
    );
}
The relation is given a name, here department. The relation indicates that the departmentId column in the Employee Model (i.e., this one) belongs to the Department Model. Here’s how this will come into play: When loading the information for an employee, you can also load any of its relations. By doing so, references to department will equate to the Department Model record that is the employee’s department. So if the $model object represents the Employee being viewed, then $model->department->name would be the name of the department that the employee is associated with.
In the Department Model, this relation is defined:
public function relations()
{
    return array('employees' => array(self::HAS_MANY, 'Employee', 'departmentId') );
}
So if $model represents a specific Department being viewed, then $model->employees is an array of Employee objects, each of which representing one Employee in that department.
The relations between Models is a key player in complex MVC sites. Through properly defined relations, associated content can be retrieved. You’ll learn more about this in the next couple of posts.
Moving on, a more trivial, but still nice, method is attributeLabels(). This method returns an associative array of fields and the labels to use for those fields in forms, error messages, and so forth. The Yii framework does a great job of making these conversations automatically, like firstName becoming First Name and departmentId becoming just Department. But you may want to still customize these. For the Employee Model, here’s what I have:
public function attributeLabels()
{
    return array(
        'id' => 'Employee ID',
        'departmentId' => 'Department',
        'firstName' => 'First Name',
        'lastName' => 'Last Name',
        'email' => 'Email',
        'ext' => 'Ext',
        'hireDate' => 'Hire Date',
        'leaveDate' => 'Leave Date',
    );
}

Complete Example


<?php
class PasswordReset extends CActiveRecord {
    public static function model($className=__CLASS__)
    {
        return parent::model($className);
    }
    public function tableName()
    {
        return 'password_reset';
    }
    public function rules()
    {
        return array(
            array('user_user_id, request_time, request_hash, request_done', 'required'),
            array('user_user_id, request_time, request_done', 'numerical'),
            array('request_done','length','min'=>6, 'max'=>1),
            array('request_time','length','min'=>6, 'max'=>10),
            array('request_hash','length','max'=>100),
            array('user_user_id, request_time, request_hash, request_done', 'safe', 'on'=>'search')
        );
    }
    public function relations()
    {
        return array(
            'User' => array(self::BELONGS_TO, 'User', 'user_user_id')
        );
    }
    public function attributeLabels()
    {
        return array(
            'request_time' => 'Request Time',
            'request_hash' => 'Request Hash',
            'request_done' => 'Request Done'	
        );
    }
    public function search()
    {
        $criteria=new CDbCriteria;

        $criteria->compare('request_time', $this->request_time, true);
        $criteria->compare('request_hash', $this->request_hash, true);
        $criteria->compare('request_done', $this->request_done, true);
        $criteria->compare('User.id', $this->User->id);
        $criteria->compare('request_done', '0', true);

        return new CActiveDataProvider($this, array(
            'criteria'=>$criteria
        ));
    }
    public function findByParameter($fieldname, $fieldvalue)
    {
        $criteria=new CDbCriteria;
        $criteria->compare($fieldname, $fieldvalue, true);		
        return new CActiveDataProvider($this, array(
            'criteria' => $criteria
        ));
    }
    public function findByParameters($parameters)
    {
        $criteria=new CDbCriteria;
        foreach ($parameters as $key => $value) {
            $criteria->compare($key, $value, true);
        }                
        return new CActiveDataProvider($this, array(
            'criteria' => $criteria,
        ));
    }
    public function getRequestList() {
        $parameters = array('request_done' => '0');
        $requests = PasswordReset::model()->findByParameters($parameters);
        return CHtml::listData($requests->getData(), 'password_reset_id', 'request_hash');
    }
}
?>

Login to your site using google account php

Step 1:
Create a Google APIs Console Account

Step 2:
Download php library

Step 3:
Write the following code to a php file:

<?php
session_start();
require_once './src/Google_Client.php';
require_once './src/contrib/Google_Oauth2Service.php';
$baseURL = "http://localhost/lightopenid/";
$client = new Google_Client();
$client->setApplicationName("Google User Info PHP Starter Application");
// Visit https://code.google.com/apis/console?api=plus to generate your
// oauth2_client_id, oauth2_client_secret, and to register your oauth2_redirect_uri.
$client->setClientId('rtrt.apps.googleusercontent.com');
$client->setClientSecret('RInoMtVa_rtrt-EQ2');
$client->setRedirectUri('http://localhost/lightopenid/');

$oauth2 = new Google_Oauth2Service($client);

if (isset($_GET['code'])) {
    $client->authenticate($_GET['code']);
    $_SESSION['token'] = $client->getAccessToken();
    header('Location: ' . filter_var($baseURL, FILTER_SANITIZE_URL));
    return;
}
if (isset($_SESSION['token'])) {
    $client->setAccessToken($_SESSION['token']);
}

if (isset($_REQUEST['logout'])) {
    unset($_SESSION['token']);
    $client->revokeToken();
}

if ($client->getAccessToken()) {
    $user = $oauth2->userinfo->get();

    // These fields are currently filtered through the PHP sanitize filters.
    // See http://www.php.net/manual/en/filter.filters.sanitize.php
    $email = filter_var($user['email'], FILTER_SANITIZE_EMAIL);
    $img = filter_var($user['picture'], FILTER_VALIDATE_URL);
    $personMarkup = "$email<div><img src='$img?sz=50'></div>";

    // The access token may have been updated lazily.
    $_SESSION['token'] = $client->getAccessToken();
} else {
    $authUrl = $client->createAuthUrl();
}
?>
<!doctype html>
<html>
<head><meta charset="utf-8"></head>
<body>
<header><h1>Google UserInfo Sample App</h1></header>
<?php if(isset($personMarkup)): ?>
<?php print $personMarkup ?>
<?php endif ?>
<?php
  if(isset($authUrl)) {
    print "<a class='login' href='$authUrl'>Connect Me!</a>";
  } else {
   print "<a class='logout' href='?logout'>Logout</a>";
  }
?>
</body></html>