Friday, October 16, 2009

AJAX in cakePhp, #cakephp, #php,

AJAX CakePHP
Using AJAX with CakePHP tutorial

CakePHP is a wonderful framework. Unfortunately, like a lot of software, documentation is severly lacking. The effort is definitely there, but with an API containing the occassional "Enter description here... unknown_type", it definitely makes things a bit more difficult. Especially for someone who adopted the RTFM mantra many years ago.

For this article, we're going to try and figure out how to get AJAX and cake to work together without having to comb cake's manual, wiki, the bakery, users' sites and tutorials and Google groups.

First things first - you'll need to have cake installed and running.

Next things second - you'll need to get the scriptaculous and prototype libraries. (I haven't tried any other AJAX libraries, but these seem to work just fine for now).

Note: there was an issue where the code crashed firefox that turned out to be caused by the prototype.js that's included in scriptaculous being the incorrect version. Therefore, I recommend downloading them separately.

You'll need to place the scriptaculous and prototype files in /app/webroot/js directory.

Now you need to add the following inside the tag of your layout file (/app/views/layout/default.thtml) to make them available:

print $html->charsetTag('UTF-8');
print $javascript->link('prototype');
print $javascript->link('scriptaculous.js?load=effects');
?>

At this point, you have 2 options - to use the RequestHandler component or not. If you're doing fancier AJAX things, you can check CakePHP's manual on RequestHandler, but to keep things simple, we won't use it.

In your controller's action, you want to add:

// controller file
var $helpers = array('Html', 'Javascript', 'Ajax');

function view() {
$this->render('layout file', 'ajax');
}

First we want to make sure we're using cake's built-in helpers, including the AJAX helper. In your action, you'll change the render action to include the ajax option, which tells cake to crunch the information and send the data somewhere rather than displaying a new page. We'll see where in a second.

What you want to do next is create a link, but not just any link. You want to enable an ajax link, and to do that you use the ajax helper that comes with cake.

// view file
echo $ajax->link('link text', '/controller/action',
array('update' => 'div id')
);

This will automatically generate a link with the appropriate attributes to output the ajax into the div you specify. Note: don't forget the forward slash - cake needs to be able to find your controller, otherwise nothing will appear to happen (no errors will be shown either).
Styling it

If you want to add a css class to the link, add the undocumented 'class' option as part of the options array.

// view file
echo $ajax->link('link text', '/controller/action',
array('update' => 'div id', 'class' => 'aclass'));

What about images?
To include an image to be linked rather than text, you simply include the html for the image in place of the first parameter, but be sure to add FALSE so the code doesn't get escaped.

echo $ajax->link('',
'/controller/action/',
array('update' => 'div id'),
null,
FALSE
);

Multiple divs
That's all fine and dandy, but what if you wanted to update more than one div at a time? To do that, you'll need to add an array of divs to update, and also use the $ajax helper to create the divs.

echo $ajax->link('link text', 'controller/action',
array('update' => array('div1', 'div2'))
);

// create the div code rather than hard-coding

echo $ajax->div('div1');
echo $ajax->divEnd('div1');

echo $ajax->div('div2');
echo $ajax->divEnd('div2');

So it updates. How do I make it look cool?
To add effects, you'll need to add the effect to the link:

$ajax->link('link text', 'controller/action',
array('update' => 'div id',
'loaded' => 'scriptaculous effect')
);

You can use loaded/loading or any of the other available options listed in the manual under helpers.
A complete example
We'll create a simple example here to demonstrate.

/**
* $Id: approot/controllers/things_controller.php
*/

class ThingsController extends AppController
{
var $name = 'Things';
var $helpers = array('Html', 'Javascript', 'Ajax');

// we're not going to use a model for this example, but
// it would be easy to use a database thanks to cake
var $uses = null;

/**
* initial page load
*/
function index() {

// preload dynamic data
$this->set('data1', 'content will update here');
$this->set('data2', 'here too');

$this->render('neat');

}//index()

/**
* display content action
*
* @param int id of content to display
*/
function view($id) {

// content could come from a database, xml, etc.
$content = array(
array('somebody is baking brownies',
'become a cake baker',),
array('knowledge is not enough',
'we must also apply - bruce lee')
);

$this->set('data1', $content[$id][0]);
$this->set('data2', $content[$id][1]);

// use ajax layout
$this->render('neat', 'ajax');

}//view()

}//ThingsController
?>




print $html->charsetTag('UTF-8');
print $javascript->link('prototype');
print $javascript->link('scriptaculous.js?load=effects');
?>





Really neat stuff here


// update both divs
echo $ajax->link('update divs', '/things/view/0',
array('update' => array('dynamic1', 'dynamic2'))
);
echo ' | ';
// use an effect
echo $ajax->link('blinders', '/things/view/1',
array('update' => array('dynamic1', 'dynamic2'),
'loading' => 'Effect.BlindDown(\'dynamic1\')')
);
?>



div('dynamic1'); ?>


divEnd('dynamic1'); ?>

div('dynamic2'); ?>


divEnd('dynamic2'); ?>

Wednesday, October 14, 2009

Plugin creation in 10 mintue, #cakephp, #php, #openSource, #MVC

Do you want to create a blog, a web management module, or anything you want for an application? Make it a CakePHP plugin and you can also put it in other applications. The main tie between a plugin and the application it has been installed into is the application's configuration (database connection etc.). Otherwise, it operates in its own little space, behaving much like it would if it were an application on its own.

To start, place your plugin files

in /app/plugins folder. Choose wisely the name of the folder for the plugin files because it will be used in many places. For any normal application, you do not need to define AppController and AppModel; that's required for the plugins. You'll need to create them before your plugin works. These two special classes are named after the plugin, and extend the parent application's AppController and AppModel. For example, the AppController will be /app/plugins/softpedia_test_controller.php and the AppModel /app/plugins/softpedia_test_model.php. If you forgot to define these classes, CakePHP will show you "Missing Controllers" error until you solve the problem.

The controllers for the plugin will be stored in /app/plugins/name_of_plugin/controller. In order to avoid namespace conflict, you should give the controller a unique name. The models of the plugin are stored in /app/plugins/name_of_plugin/models. Next, you will specify the place where you will put the plugin views. Views for the plugin have the same functions as in normal applications. Place the views in /app/plugins/name_of_plugin/views folder.

Before starting to create your CakePHP application, you should consider the following conventions:
- model filenames are singular, capitalized for single-word models, and UpperCamelCased for multi-word models.Also model filenames use a lower-case underscored syntax: e.g: softpedia_test.php
- table names are plural and lowercased
- foreign keys should always be: table_name_in_singular_form_id: user_id (foreign key) �� users (table)
- controller filenames are plural and underscored with "controller" appended: controller_name_controller.php

You can find all the conventions in the manual.

Karry Lugar Bill: American Aid for Pakistan: # pakistan-news ,# news, #karry lugar bill

Monday, October 12, 2009

redirect(), Header(), #cakephp, #cake, #opensource

This is our PHP redirect() function, it has been tested with PHP versions >= 4.2.0. Seen a lot of requests for this on various mailing lists so we thought we'd share.
We've added support for different HTTP/1.1 3XX status codes. Each of the response codes tell the requesting User-Agent how to respond as described below.
In the W3C specification it's stated that the server should also give some content back for the User-Agent to render if it does not obey the redirect. This redirect function will output some pretty HTML if the headers have already been sent following the W3C intentions.
301 Moved Permanently - Forget the old page existed
302 Found - Use the same method (GET/POST) to request the specified page.
303 See Other - Use GET to request the specified page. Use this to redirct after a POST.
307 Temporary Redirect - Good for response to POST.
Usage example
// Do stuff here before sending headers
redirect('/')
redirect("/my/page")
redirect("http://www.foo.bar/page.htm",303)
redirect("./index.php",307)
?>
The redirect function itself
You may copy and paste this code freely where you need to, please give us credit it if you use it
// func: redirect($to,$code=307)
// spec: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
function redirect($to,$code=301)
{
$location = null;
$sn = $_SERVER['SCRIPT_NAME'];
$cp = dirname($sn);
if (substr($to,0,4)=='http') $location = $to; // Absolute URL
else
{
$schema = $_SERVER['SERVER_PORT']=='443'?'https':'http';
$host = strlen($_SERVER['HTTP_HOST'])?$_SERVER['HTTP_HOST']:$_SERVER['SERVER_NAME'];
if (substr($to,0,1)=='/') $location = "$schema://$host$to";
elseif (substr($to,0,1)=='.') // Relative Path
{
$location = "$schema://$host/";
$pu = parse_url($to);
$cd = dirname($_SERVER['SCRIPT_FILENAME']).'/';
$np = realpath($cd.$pu['path']);
$np = str_replace($_SERVER['DOCUMENT_ROOT'],'',$np);
$location.= $np;
if ((isset($pu['query'])) && (strlen($pu['query'])>0)) $location.= '?'.$pu['query'];
}
}

$hs = headers_sent();
if ($hs==false)
{
if ($code==301) header("301 Moved Permanently HTTP/1.1"); // Convert to GET
elseif ($code==302) header("302 Found HTTP/1.1"); // Conform re-POST
elseif ($code==303) header("303 See Other HTTP/1.1"); // dont cache, always use GET
elseif ($code==304) header("304 Not Modified HTTP/1.1"); // use cache
elseif ($code==305) header("305 Use Proxy HTTP/1.1");
elseif ($code==306) header("306 Not Used HTTP/1.1");
elseif ($code==307) header("307 Temporary Redirect HTTP/1.1");
else trigger_error("Unhandled redirect() HTTP Code: $code",E_USER_ERROR);
header("Location: $location");
header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
}
elseif (($hs==true) || ($code==302) || ($code==303))
{
// todo: draw some javascript to redirect
$cover_div_style = 'background-color: #ccc; height: 100%; left: 0px; position: absolute; top: 0px; width: 100%;';
echo "
\n";
$link_div_style = 'background-color: #fff; border: 2px solid #f00; left: 0px; margin: 5px; padding: 3px; ';
$link_div_style.= 'position: absolute; text-align: center; top: 0px; width: 95%; z-index: 99;';
echo "
\n";
echo "

Please See: ".htmlspecialchars($location)."

\n";
echo "
\n
\n";
}
exit(0);
}

Friday, October 9, 2009

How send Email using Cakephp, #cakephp, #php, #codignitor, #opensource

I know the title of this post a little bit confusing but let me explain what I want to tell.

You are using CakePHP’s email component and you should set the same information in each time before you send your email like server address, username, password etc.

Just create a new file mailer.php with the following content and drop it into your CakePHP application components folder (I like convention over configuration! ).
App::import('Component', 'Email');
class MailerComponent extends EmailComponent
{
var $from = 'ME ';
var $replyTo = 'noreply@localhost';
var $sendAs = 'both';
var $delivery = 'smtp';
var $xMailer = 'Postman';
var $smtpOptions = array(
'port'=> 25,
'host' => 'serveradress',
'timeout' => 30,
'username' => 'username',
'password' => 'password'
);
}
?>
And right now you have a new component with the name “Mailer” and its server configuration is predefined. You can reuse it without being affected by any kind of mail server change.

You can define a new function inside your controller (_sendEmail() in our case) and make the email sending process more painless.

view sourceprint?
class AnyController extends AppController
{
function contact()
{
if ($this->_sendEmail('Name', 'blabla@fakeemail', 'Grate site!')) {
$this->Session->setFlash(__("Thank you", true));
} else {
$this->Session->setFlash('Damn it!');
}
}

function _sendEmail($name, $email, $message)
{
$this->Mailer->to = 'info@localhost';
$this->Mailer->subject = __("Site Contact", true);
$this->Mailer->template = 'contact';

$this->set('name', $name);
$this->set('email', $email);
$this->set('message', $message);
$this->Mailer->send();

$this->log( $this->Mailer->subject . ' -> Name:'. $name .' | E-posta: '. $email .' | Message: '. $message .' | smtp error: '. serialize($this->Mailer->smtpError) );

return $this->Mailer->smtpError ? false : true;
}
}

Wednesday, September 30, 2009

using the Prototype JavaScript Library its really magic, #php, #cakephp, #opensource, #JavaScript library

As common or rare as it may be for someone to need the ability to select and deselect checkboxes in a form, here is a way to do it using the Prototype JavaScript Library. I recently needed a way to do this for the Private Message functionality of a Web Application I'm working on. The example code below is taken from this Application.
First make the Event observers:

if($('box_list') != null)
{
Event.observe($('checkall'),'click',pm_checkall,true);
Event.observe($('clearall'),'click',pm_clearall,true);
Event.observe($('checkread'),'click',pm_checkread,true);
Event.observe($('checkunread'),'click',pm_checkunread,true);
}
Then make the functions to handle selecting and deselecting the checkboxes. Here I've made a function to loop over all the form elements and operate on the ones we want to change; and 4 functions that tell the main function what to do based on the Event observed:

function pm_checkall(e)
{
pm_check_uncheck(true);
}
function pm_clearall(e)
{
pm_check_uncheck(false);
}
function pm_checkread(e)
{
pm_check_uncheck(false,"unread");
pm_check_uncheck(true,"read");
}
function pm_checkunread(e)
{
pm_check_uncheck(false,"read");
pm_check_uncheck(true,"unread");
}
function pm_check_uncheck(val,group)
{
lst = document.forms['box_list'];
len = lst.elements.length;
var i=0;
for(i=0; i {
if(group)
{
if(lst.elements[i].className == group)
{
lst.elements[i].checked = val;
}
}
else
{
if(lst.elements[i].type == "checkbox")
{
lst.elements[i].checked = val;
}
}
}
}
Now it's time to add the correct markup to the page. I use Smarty for templates so the markup below shows the foreach loop where I generate the checkboxes for each message.



{foreach from=$message_list key=key item=message}





{/foreach}
{$message.subject} {$message.author_name}{$message.created_on|date_format}


Select:
All
None
Read
Unread

Friday, September 18, 2009

Facebook Six fight for right to bag boss

ARJUN RAMACHANDRAN AND ASHER MOSES
September 17, 2009
Six prison workers must wait until next week to find out if they will be sacked for criticising their bosses on Facebook.

The officers have each been sent a letter indicating the Corrective Services Department is considering sacking them for misconduct over comments they made on Facebook, which the department described as "bullying" and "harassment".

But the public sector union - which regards the sacking threat as an attempt to stifle dissent - has taken the matter to the Industrial Relations Commission.

It wants the IRC to put a hold on any sacking attempts and also to consider a change to the award safeguarding the rights of workers to speak freely outside work hours.

The IRC hearing, which opened yesterday, has been adjourned until Tuesday.

Harvard Discovers Six Sources Of Alternative Energy That Don't Suck!


Renewable energy sounds great, but there are a bunch of problems. For example, half the time you can't even use it.

It's hard to get wind power when the wind isn't blowing, for example. Likewise, it's hard to get solar power when it's cloudy.

So researchers are dumping billions of dollars into trying to find alterative energy technologies that provide power as consistently as, say, oil. Or nukes.

And here's the good news: They say they're this close to cracking the code that will lead to unlimited energy for all.

The Harvard Business Review has identified six sources of permanent alternative energy at various stages of development. There is no guarantee they will work, of course. But at least they're trying.
6 Sources Of Alternative Energy That Don't Suck→

Thursday, September 17, 2009

Pakistani's Politics, parlimantarina in Repulsive on live show. #Kal Tak on #tv channel #Express TV


A woman can be recognized by her way communicating. I think (I am sorry to say) she was one those in democratic party which she was defending herself by using abusive word (hera mindi she know well it is actually in Pakistan). she should never called by any Tv channel in future and she should expel out from Party after declaring a show card for her.
SEE Video also

Thursday, August 27, 2009

Data Validation in #cakePhp, #open Source, #php

Cake goes a long way in taking the monotony out of form input validation. Everyone hates coding up endless forms and their validation routines. CakePHP makes it easier and faster.

To take advantage of the validation features, you'll need to use Cake's FormHelper in your views. The FormHelper is available by default to all views at $form.

Here's our add view:

Plain Text View
create('Post');echo $form->input('title');echo $form->input('body', array('rows' => '3'));echo $form->end('Save Post');?>
Here, we use the FormHelper to generate the opening tag for an HTML form. Here's the HTML that $form->create() generates:

Plain Text View

If create() is called with no parameters supplied, it assumes you are building a form that submits to the current controller's add() action (or edit() action when id is included in the form data), via POST.

The $form->input() method is used to create form elements of the same name. The first parameter tells CakePHP which field they correspond to, and the second parameter allows you to specify a wide array of options - in this case, the number of rows for the textarea. There's a bit of introspection and automagic here: input() will output different form elements based on the model field specified.

The $form->end() call generates a submit button and ends the form. If a string is supplied as the first parameter to end(), the FormHelper outputs a submit button named accordingly along with the closing form tag. Again, refer to Chapter "Built-in Helpers" for more on helpers.

Now let's go back and update our /app/views/posts/index.ctp view to include a new "Add Post" link. Before the , add the following line:

Plain Text View
link('Add Post',array('controller' => 'posts', 'action' => 'add'))?>
You may be wondering: how do I tell CakePHP about my validation requirements? Validation rules are defined in the model. Let's look back at our Post model and make a few adjustments:

Plain Text View
array( 'rule' => 'notEmpty' ), 'body' => array( 'rule' => 'notEmpty' ) );}?>
The $validate array tells CakePHP how to validate your data when the save() method is called. Here, I've specified that both the body and title fields must not be empty. CakePHP's validation engine is strong, with a number of pre-built rules (credit card numbers, email addresses, etc.) and flexibility for adding your own validation rules. For more information on that setup, check the Data Validation chapter.

Now that you have your validation rules in place, use the app to try to add a post with an empty title or body to see how it works. Since we've used the input() method of the FormHelper to create our form elements, our validation error messages will be shown automatically.



Thursday, August 20, 2009

Html link in plugin using #cakephp, #php, #opensource, # programming

when you have to make link for plugin controller action while you are not working in plugin. I means makeing link to plugin from view is pretty simple
like
i have app/plugin/Testplugin/testplugin_conrollers
and i am at this url
http://localhot/projectname/user/index

So in view/users/index.ctp i will make url link to testplugin index function
link('Configure', array('plugin' =>'Testplugin', 'controller' => 'testplugin', 'action' => 'index'));?>

Monday, August 17, 2009

captcha in cakephp # php, # cakephp, #opensource

download libraray
http://www.captcha.ru/kcaptcha.zip
unzip and past it in vendor
app/vendor/place here
-----------------------------------------------------
code controller model and view as normal
------------------------------------------------------
class KCaptchaComponent extends Object
{
function startup(&$controller)
{
$this->controller = $controller;
}

function render()
{
vendor('kcaptcha/kcaptcha');
$kcaptcha = new KCAPTCHA();
$this->controller->Session->write('captcha', $kcaptcha->getKeyString());
}
}
?>

save this as [web]/app/controllers/components/kcaptcha.php

Model of users
class User extends AppModel
{
var $name = 'User';

/**
* validation rules
*/
var $validate = array (
'user_login' => array(
'exists' => array(
'rule' => array( 'checkUnique', 'user_login' ),
'message' => 'The Username you entered has been taken.'
),
'minLength' => array(
'rule' => array('minLength', 3),
'message' => 'Username must at least be 3 character long.'
)
),
'user_pass' => array(
'mingLength' => array(
'rule' => array('minLength', '6'),
'message' => 'Mimimum 6 characters long'
)
),
'user_name' => array(
'minLength' => array(
'rule' => array('minLength', 3),
'message' => 'Username must at least be 3 character long.'
)
),
'user_email' => array (
'email' => array(
'rule' => 'email',
'message' => 'Please supply a valid email address.'
),
'exists' => array(
'rule' => array( 'checkUnique', 'user_email' ),
'message' => 'The email you entered has been registered.'
)
)
);

/**
* Validate if the data is unique.
*
* @param $data The data to be compared.
* @param $fieldName The field name to check.
* @return true If the field name unique. False otherwise.
*/
function checkUnique( $data, $fieldName ) {
$valid = false;
if(isset($fieldName) && $this->hasField($fieldName)) {
$valid = $this->isUnique(array($fieldName => $data));
}
return $valid;
}
}
?>


Controller
class UsersController extends AppController
{
var $name = 'Users';
var $components = array('Auth', 'KCaptcha');

function beforeFilter() {
$this->Auth->fields = array('username' => 'user_login', 'password' => 'user_pass');
$this->Auth->allow('register','kcaptcha' );
}


/**
* This method handle the user registration process.
* It will first of all, get the user basic information.
* After user submit the information, a hash key will be generated and
* stored in the database. An email will then send to user and pending
* for user activation
*/
function forget() {


if (!empty($this->data))
{
$username = $this->data['User']['username'];
if( strtolower($this->data['User']['captcha']) == strtolower( $this->Session->read('captcha'))) {

if ($user = $this->User->find(array('or' => array('username' => $username, 'email' => $username)), 'id, username, password, email, first_name, last_name'))
{

extract($user['User']);
$reset_code = Security::hash($username.$id.$password);
$this->set('reset_code', $reset_code);
$this->User->id = $id;
if($this->User->saveField('password_reset', $reset_code) &&
$this->_sendMailTemplate($email, $this->forgetPassword, $this->forgetSubject, 'forget')) {
$this->Session->setFlash('A password reset request has been sent. Check you email address: '.$username);
} else {
$this->Session->setFlash('Error resetting password. Contact Administrator');
}
$this->redirect('/users/login');
}
else {
$this->Session->setFlash('User does not exist.');
}
unset( $this->data['User']['captcha']);
}
else{
$this->Session->setFlash('captcha verification failed');
}
}
}
function kcaptcha()
{
$this->KCaptcha->render();
}
}
?>

views/users/forget.ctp
flash('auth'); ?>
flash(); ?>

create('User', array('action' => 'forget'));?>

Forget Password
echo $form->input('username', array('label' => 'Username or Email Address'));
echo $form->input('captcha', array( 'label' => 'Please type the text presented in the image : ',
'before' => 'user image html tag here="'. $form->url('/users/kcaptcha').'" '));
?>

end('Submit');?>

Saturday, August 8, 2009

Baitullah Mehsud is alive, still holding command of Taliban fighters: Hakimullah Mehsud

Tehrik-e-Taliban Pakistan, a coalition of various Taliban groups, has refuted the reports about killing of Taliban supremo Baitullah Mehsud in a drone strike. Hakimullah Mehsud, an influential Taliban commander while refuting the reports has said the Taliban will release a video of Baitullah Mehsud. He said Baitullah Mehsud was alive and still holding the command of Taliban fighters. He promised to release a recorded video of Mehsud within two to three days.


URL
http://www.nation.com.pk/pakistan-news-newspaper-daily-english-online/Politics/08-Aug-2009/Baitullah-Mehsud-is-alive-still-holding-command-of-Taliban-fighters-Hakimullah-Mehsud

Thursday, August 6, 2009

USE OF IF CONDITION IN FIND QUERY IN CONDITION ARRAYIN #CAKEPHP, #BAKERY ALL THING, #MVC

$condition = array();

if($this->data['Comment']['module_name'] == 'news' && $this->data['Comment']['news'] == 'all')
$condition['Comment.content_type'] = $this->data['Comment']['module_name'];
if($this->data['Comment']['module_name'] == 'opinions' && $this->data['Comment']['opinions'] == 'all')
$condition['Comment.content_type'] = $this->data['Comment']['module_name'];
if($this->data['Comment']['module_name'] == 'classifieds' && $this->data['Comment']['classifieds'] == 'all')
$condition['Comment.content_type'] = $this->data['Comment']['module_name'];



than
use find query
$result = $this->Comment->find('all', array('recursive'=> -1,'fields'=>array('*'),'conditions' => array('Comment.created >' => $fromDate,'Comment.created <' => $toDate, $condition)));

Friday, July 24, 2009

http://www.youtube.com/watch?v=5_ZPSfXWsDw&feature=PlayList&p=B6901E61C4196551&playnext=1&playnext_from=PL&index=44

little champs in commedy

Musharraf announces team of legal experts to defend

The former President General (rtd) Pervez Musharraf constituted a committee of lawyers to defend him in cases filed against him at the Supreme Court, a private TV reported Friday. The legal committee of the former president will be headed by Abdul Hafeez Pirzadah with Khalid Ranjha, Malik Abdul Qayyum and Chaudhry Fawwad as committee members. Talking to Chaudhry Fawwad by phone from London, Pervez Musharraf said he did everything during his era for national interest. The former President is quoted saying, ‘I saw good time, will see bad times now.’ It should be noted that the Supreme Court issued summon notice to the former president directing him to appear before court on July 29 in cases relating judges’ appointment and emergency.

Thursday, July 23, 2009

the top to bottom persistent internationalization tutorial

For some developers, allowing a website to support multiple languages is essential. Luckily cakePHP 1.2 has the foundations available to make this possible.
Before forging ahead, I'd like a disclaimer. I don't claim this tutorial to be uniquely mine, it's an amalgamation of techniques from several pages and sites. Neither is it the most comprehensive and in-depth guide.

That said, I certainly hope after using this guide you can quickly and easily implement multiple languages in your cake app without needing to skip around the place. If I fall short of this and you have suggestions, leave a comment.

Once you complete this tutorial your site will be able to:

1. display multiple languages
2. allow users to switch languages
3. store language settings in cookies, so returning visitors don't need to re-select their preferred language

The sites that I build typically require 3 languages:

1. British English(en-gb)
2. Simplified Chinese(zh-cn)
3. Traditional Chinese(zh-tw)

So throughout this document, I'll be using them as my reference languages. Your site may support more or less languages.
Step 1: Setup the directories for your messages

$ cd cake/app/locale/

$ mkdir en_gb

$ mkdir en_gb/LC_MESSAGES

$ mkdir zh_tw

$ mkdir zh_tw/LC_MESSAGES

$ mkdir zh_cn

$ mkdir zh_cn/LC_MESSAGES

This will create the minimum folders required for each language our site needs to support.

To find your language code(s) refer to http://api.cakephp.org/1.2/l10n_8php-source.html#l00180 Download code //this is only a sample. don't add this to your code.
'nl' => array(
'language' => 'Dutch (Standard)',
'locale' => 'dut',
'localeFallback' => 'dut',
'charset' => 'utf-8'
),
'pl' => array(
'language' => 'Polish',
'locale' => 'pol',
'localeFallback' => 'pol',
'charset' => 'utf-8'
),
'sk' => array(
'language' => 'Slovack',
'locale' => 'slo',
'localeFallback' => 'slo',
'charset' => 'utf-8'
),
By studying the sample above, we can see that directory names are actually the locale:

* 'dut' is the correct directory name(locale) for 'nl'
* 'pol' is the correct directory name(locale) for 'pl'
* 'slo' is the correct directory name(locale) for 'sk'

Step 2: Write some strings to translate.
View Template:
Download code pageTitle = __('pageTitle_home', true); ?>







note: The 2nd parameter controls whether a message should be returned or echo'd
So when you are working with a template, use:
PHP Snippet:
Download code And when you are working with code, use:
PHP Snippet:
Download code
Step 3: Let's build a database from our PHP and templates.

$ cd cake/app/

$ cake extract

This will recursively go through all the folders and check both your .php and .ctp files for all of those __() functions you typed. Once it's complete, you should have a nice message template file named default.pot file inside cake/app/locale/

So let's copy this message template file into the right directories for each language.

$ cd cake/app/locale/

$ cp default.pot locale/en_gb/LC_MESSAGES/default.po

$ cp default.pot locale/zh_tw/LC_MESSAGES/default.po

$ cp default.pot locale/zh_cn/LC_MESSAGES/default.po


note: at this point in time, you can freely edit the default.po files(they're just text) and start translating strings. Changes made to these files will automatically be rendered in your views.

Here are some short snippets from my default.po files.

Download code // locale/zh_cn/LC_MESSAGES/default.po
msgid "footer_copyright"
msgstr "??? � 2007. ????"

// locale/zh_tw/LC_MESSAGES/default.po
msgid "footer_copyright"
msgstr "??? � 2007. ????"

// locale/en_gb/LC_MESSAGES/default.po
msgid "footer_copyright"
msgstr "Education Bureau � 2007. All rights reserved."
Step 4: Change the default language
A fresh install of cakePHP is set to use American English, so for the rest of us: we need that changed.
Download code // config/bootstrap.php
define(DEFAULT_LANGUAGE, 'zh-tw');
Step 5: Let users change the language
Component Class:
Download code class P28nComponent extends Object {
var $components = array('Session', 'Cookie');

function startup() {
if (!$this->Session->check('Config.language')) {
$this->change(($this->Cookie->read('lang') ? $this->Cookie->read('lang') : DEFAULT_LANGUAGE));
}
}

function change($lang = null) {
if (!empty($lang)) {
$this->Session->write('Config.language', $lang);
$this->Cookie->write('lang', $lang, null, '+350 day');
}
}
}
?> Thanks Nasko for pointing out that Cookie->write() does not accept timestamps
Controller Class:
Download code class P28nController extends AppController {
var $name = 'P28n';
var $uses = null;
var $components = array('P28n');

function change($lang = null) {
$this->P28n->change($lang);

$this->redirect($this->referer(null, true));
}

function shuntRequest() {
$this->P28n->change($this->params['lang']);

$args = func_get_args();
$this->redirect("/" . implode("/", $args));
}
}
?>
Controller Class:
Download code //app_controller.php
class AppController extends Controller {
var $components = array('P28n');
}
?> The final piece of code, are some custom routes that need to be added to cake/app/config/routes.php
Download code //route to switch locale
Router::connect('/lang/*', array('controller' => 'p28n', 'action' => 'change'));

//forgiving routes that allow users to change the lang of any page
Router::connect('/eng?/*', array(
'controller' => "p28n",
'action' => "shuntRequest",
'lang' => 'en-gb'
));

Router::connect('/zh[_-]tw/*', array(
'controller' => "p28n",
'action' => "shuntRequest",
'lang' => 'zh-tw'
));

Router::connect('/zh[_-]cn/*', array(
'controller' => "p28n",
'action' => "shuntRequest",
'lang' => 'zh-cn'
));
?>
Step 6: Links to change language
View Template:
Download code









link($html->image('en_gb.gif'), '/lang/en-gb', null, null, false); ?>
link($html->image('zh_tw.gif'), '/lang/zh-tw', null, null, false); ?>
link($html->image('zh_cn.gif'), '/lang/zh-cn', null, null, false); ?>


link($html->image('en_gb.gif'), '/en-gb/news', null, null, false); ?>
link($html->image('zh_tw.gif'), '/zh-tw/news', null, null, false); ?>
link($html->image('zh_cn.gif'), '/zh-cn/news', null, null, false); ?>

CakePHP URL-based language switching for i18n and l10n

nuts and bolts of cakephp
CakePHP URL-based language switching for i18n and l10n (internationalization and localization)
Posted in CakePHP by teknoid on November 28, 2008

I should preface this post by saying that it does not cover the basics of i18n and l10n so, please, first take a look at the manual on how to get the basics going.

To better understand the goal and why some things were done the way they were, I’ll summarize the requirements:

1. The app has to support two languages or more (in this case English and Russian)
2. Default language is English
3. The language switching is based on a URL param
4. The URL format should be: example.com/eng/controller/action
5. Language choice should persist in the session and a cookie

Just a note here… there are other ways to determine the language requested by the user, for example it could come from a domain name like eng.example.com or rus.example.com. Hopefully the approach outlined here will also be helpful if other methods of language switching are used in your app…

Also, worth while to mention, that having language name in the URL (as opposed to just reading it from the session or cookie) helps with SEO… I won’t bore you here with details, but basically it helps to ensure that a variation of each page, based on the language param in the URL, is properly indexed by the search engines. Thus, each indexed page can be found later in the native language of the user.

Last, but not least, CakePHP uses three letter language name abbreviation, based on this, so I figure, should be fine to use the same in the URL’s.

Alright, so looking at the URL format, instantly raises a question… how do we tack on the language name to the “front” of each URL?

Thankfully the Router accomplishes that pretty easily (in app/config/routes.php):
view plaincopy to clipboardprint?

1. Router::connect('/:language/:controller/:action/*',
2. array(),
3. array('language' => '[a-z]{3}'));

Router::connect('/:language/:controller/:action/*',
array(),
array('language' => '[a-z]{3}'));

It takes a ‘language’ parameter and throws it to the front of the URL, just as we need it.

Now, we need to specify a default language to use, I just add this to my app/config/core.php


Configure::write('Config.language', 'eng');

So, when someone comes to the http://example.com/users/home, the site is displayed in English by default. Then we usually see a link somewhere (with a little flag next to it :)), to switch to another language.

In cake we can make those language-switching links like this:


$html->link('Русский', array('language'=>'rus'));

Notice that we set the language param, which we’ll rely on to do our switching. Providing no other params, will simply reload the current page (in the new language) with the param tacked to the front of the URL (more about this later).

Side note, it’s not a good idea to use the __() translation function on language-switching links… If I get to the site and it’s displayed in the language I can’t understand even remotely, the only savior would be a link in my native language, which indicates that i can switch to it (and well, a little flag would help too :))

So now we actually need the code to switch the language, when a user clicks on the link, like above.

It’s best done in the App Controller, kinda like here:
view plaincopy to clipboardprint?

1. var $components = array('Session', 'Cookie');
2.
3. function beforeFilter() {
4. $this->_setLanguage();
5. }
6.
7. function _setLanguage() {
8.
9. if ($this->Cookie->read('lang') && !$this->Session->check('Config.language')) {
10. $this->Session->write('Config.language', $this->Cookie->read('lang'));
11. }
12. else if (isset($this->params['language']) && ($this->params['language']
13. != $this->Session->read('Config.language'))) {
14.
15. $this->Session->write('Config.language', $this->params['language']);
16. $this->Cookie->write('lang', $this->params['language'], null, '20 days');
17. }
18. }

var $components = array('Session', 'Cookie');

function beforeFilter() {
$this->_setLanguage();
}

function _setLanguage() {

if ($this->Cookie->read('lang') && !$this->Session->check('Config.language')) {
$this->Session->write('Config.language', $this->Cookie->read('lang'));
}
else if (isset($this->params['language']) && ($this->params['language']
!= $this->Session->read('Config.language'))) {

$this->Session->write('Config.language', $this->params['language']);
$this->Cookie->write('lang', $this->params['language'], null, '20 days');
}
}

Let’s take a look at the code quickly and consider some scenarios…

I created a separate method _setLanguage();, the reason I like doing this is that it keeps the beforeFilter() cleaner, which already has enough crap in there usually.
Secondly, it can be overridden in the child controllers, if required.

So let’s consider some user-case scenarios:

1.

The user comes to the site for the very first time

In this case the default language is read from the core.php file, so the site is set to English
2.

The user starts clicking around the site for the very first time in his native English

Nothing really needs to be done, so we can happily skip that part
3.

The user comes to the site and has to switch the language to Russian

Thankfully he sees a link to do so, and clicks on it. Now we check our else if, since no cookie or session with configured language exist yet. We see that the link has a /rus/ param in the URL and it is not yet stored in the session, therefore we write the new value of the default language to the session and the cookie.
4.

The above user browses around the site, leaves, and then comes back

The session value is still present and therefore the site is automagically translated to Russian. This is good if the user forgot or doesn’t care to use links like example.com/rus/controller/action, because even plain links like example.com/controller/action will display the site in the right language because of the session value.
5.

The above user closes the browser, goes out hunting for wild boars, and comes to the site on some other day

Now we rely on our previously stored cookie to read in the language and ensure we don’t override anything that might be in the session already. (the first if )
6.

Now if the user decides to read the site in English

We pretty much follow through the same steps as above.

Now the last thing we need to do is to ensure that a URL param gets automatically added to all the links on the site, if a given language is chosen. Remember, that this is important to have such links for SEO as well.

Well, we’re sure as hell not going to supply the ‘language’ param manually to each link, so let’s override the cake’s default url() method to ensure the language param is now added to all links.

We create app_helper.php in /app/ (same place for app_controller.php and app_model.php), something like this:
view plaincopy to clipboardprint?

1. class AppHelper extends Helper {
2.
3. function url($url = null, $full = false) {
4. if(!isset($url['language']) && isset($this->params['language'])) {
5. $url['language'] = $this->params['language'];
6. }
7.
8. return parent::url($url, $full);
9. }
10.
11. }

class AppHelper extends Helper {

function url($url = null, $full = false) {
if(!isset($url['language']) && isset($this->params['language'])) {
$url['language'] = $this->params['language'];
}

return parent::url($url, $full);
}

}

Basically we check if ‘language’ param is already in the URL if it is, we don’t need to worry about it.
If not, and $this->params['language'] is available we pre-pend the required language to the URL.
The rest of the site, and all standard links will now include that ‘language’ param at the front of the URL (again, good for SEO).

And that’s pretty much it, even though the post was a bit long-winded (and beer to you, if you’ve made through the whole thing) it is quite nice to be able to do i18n & l10n in just about 15 lines of code.

A little disclaimer: even though the code seems to work fine, it is still experimental… so if you find some problems I haven’t yet encountered, please be sure to let me know.

P.S. Here’s a sampe test view, from which you can generate your .po files (easily done with cake i18n console command, but this is a topic for another tutorial and there are plenty of them “out there”).
view plaincopy to clipboardprint?

1. 2. __('This is only a test message');
3. ?>
4.
5.


6. link(__('Regular link', true), array('action'=>'test')); ?>
7.


8.
9.


10. link(__('Regular link two', true), array('controller'=>'users', 'action'=>'test5', 'some stuff')); ?>
11.


12.
13.


14. link('English', array('language'=>'eng')); ?>
15.


16.
17.


18. link('Русский', array('language'=>'rus')); ?>
19.

Wednesday, July 22, 2009

how to create Plugin in cake php

Creating a Plugin
As a working example, let's create a new plugin that orders pizza for you. What could be more useful in any CakePHP application?
To start out, we'll need to place our plugin files inside the /app/plugins folder. The name of the parent folder for all the plugin files
is important, and will be used in many places, so pick wisely. For this plugin, let's use the name 'pizza'. This is how the setup will
eventually look:
Pizza Ordering Filesystem Layout
/app
/plugins
/pizza
/controllers <- plugin controllers go here
/models <- plugin models go here
/views <- plugin views go here
/pizza_app_controller.php <- plugin's AppController, named after the plugin
/pizza_app_model.php <- plugin's AppModel, named after the plugin

While defining an AppController and AppModel for any normal application is not required, defining them for plugins is. You'll
need to create them before your plugin works. These two special classes are named after the plugin, and extend the parent
application's AppController and AppModel. Here's what they should look like:
Pizza Plugin AppController: /app/plugins/pizza_app_controller.php

class PizzaAppController extends AppController
{
//...
}
?>
Pizza Plugin AppModel: /app/plugins/pizza_app_model.php
class PizzaAppModel extends AppModel
{
//...
}
?>
If you forget to define these special classes, CakePHP will hand you "Missing Controller" errors until the problem is rectified.

Section 2
Plugin Controllers
Controllers for our pizza plugin will be stored in /app/plugins/pizza/controllers. Since the main thing we'll be tracking is pizza
orders, we'll need an OrdersController for this plugin.

While it isn't required, it is recommended that you name your plugin controllers something relatively unique in order to avoid
namespace conflicts with parent applications. Its not a stretch to think that a parent application might have a UsersController,
OrderController, or ProductController: so you might want to be creative with controller names, or prepend the name of the plugin to
the classname (PizzaOrdersController, in this case).
So, we place our new PizzaOrdersController in /app/plugins/pizza/controllers and it looks like so:
/app/plugins/pizza/controllers/pizza_orders_controller.php
class PizzaOrdersController extends PizzaAppController
{
var $name = 'PizzaOrders';
function index()
{
//...
}
function placeOrder()
{
//...
}
}
?>
Note how this controller extends the plugin's AppController (called PizzaAppController) rather than just the parent application's
AppController.

Section 3
Plugin Models
Models for the plugin are stored in /app/plugins/pizza/models. We've already defined a PizzaOrdersController for this plugin, so
let's create the model for that controller, called PizzaOrders (the classname PizzaOrders is consistent with our naming scheme, and
is unique enough, so we'll leave it as is).
/app/plugins/pizza/models/pizza_order.php
class PizzaOrder extends PizzaAppModel
{
var $name = 'PizzaOrder';
}
?>
Again, note that this class extends PizzaAppModel rather than AppModel.

Section 4
Plugin Views
Views behave exactly as they do in normal applications. Just place them in the right folder inside of the /app/plugins/[plugin]/views
folder. For our pizza ordering plugin, we'll need at least one view for our PizzaOrdersController::index() action, so let's include that
as well:
/app/plugins/pizza/views/pizza_orders/index.thtml

Order A Pizza


Nothing goes better with Cake than a good pizza!




Section 5
Working With Plugins
So, now that you've built evertything, it should be ready to distribute (though we'd suggest you also distribute a few extras like a
readme, sql file, etc.).
Once a plugin as been installed in /app/plugins, you can access it at the URL /pluginname/controllername/action. In our pizza
ordering plugin example, we'd access our PizzaOrdersController at /pizza/pizzaOrders.
Some final tips on working with plugins in your CakePHP applications:
When you don't have a [Plugin]AppController and [Plugin]AppModel, you'll get missing Controller errors when trying to
access a plugin controller.

1.
You can have a default controller with the name of your plugin. If you do that, you can access it via /[plugin]/action. For
example, a plugin named 'users' with a controller named UsersController can be accessed at /users/add if there is no plugin
called AddController in your [plugin]/controllers folder.

2.
Plugins will use the layouts from the /app/views/layouts folder by default.

3.
You can do inter-plugin communication by using
$this->requestAction('/plugin/controller/action');
in your controllers.

4.
If you use requestAction, make sure controller and model names are as unique as possible. Otherwise you might get PHP
"redefined class ..." errors.

local users at twitter

Hy ,
How can i find local user at twitter according to particular location
thanks