__() function. For example, for echoed text like the following:
echo 'This text';
Replace it with the following:
__('This text');
For variables, such as the following:
$directions = array('N' => 'North', 'S' => 'South', 'E' => 'East', 'W' => 'West');
Replace it with the following:
$directions = array('N' => __('North', true), 'S' => __('South', true), 'E' => __('East', true), 'W' => __('West', true));
Then build your /app/locale/default.pot
file using the console
# cd /app
# /cake/console/cake i18n extract
Accept default options and the file is created.
Edit the /app/locale/default.pot
with a program like Poedit, add your translations, then save the file in the appropriate directory as a catalog (.po file) e.g. /app/locale/spa/LC_MESSAGES/default.po
Be sure to re-extract and update the .pot and catalog files every time you add new text to your application.
To add a language to the beginning of each path add the following to your /app/config/routes.php
:
/* For internationalization */
Router::connect('/:language/:controller/:action/*', array(), array('language' => '[a-z]{3}'));
To specify a default language, add the following to your /app/config/core.php
and add the following lines:
/* For internationalization */
Configure::write('Config.language', 'eng');
Now to create a language switching link use the following:
echo $this->Html->link('EspaƱol', array('language' => 'spa'));
Ensure Cookies and Session components are loaded and put the following functions in the /app/app_controller.php
:
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'], false, '20 days');
}
}
Lastly, create the /app/app_helper.php
file
params['language'])) {
$url['language'] = $this->params['language'];
}
return parent::url($url, $full);
}
}
?>
Monday, July 2, 2012
Multi-language Support
To allow your application to appear in multiple languages, first change all displayable text to utilize the
Monday, March 12, 2012
Form Helper
When using the Form helper to create a form, there are some options you can utilize to make your forms better.
Radio
The following form radio selection is named 'Radio name' and lists two options, 'label1' and 'label2', with 'label1' selected by default.echo $this->Form->input('Radio name', array('type' => 'radio', 'legend' => false, 'options' => array('value1' => 'label1', 'value2' => 'label2'), 'default' => 'value1'));
Selection
The following form selection displays a select box with 4 directions and their corresponding single letter values and includes an empty first selection and a default selection of West.$dirs = array('N' => 'North', 'E' => 'East', 'S' => 'South', 'W' => 'West'); echo $this->Form->input('street_dir', array('label' => __('Direction', true), 'type' => 'select', 'options' => $dirs, 'empty' => true, 'default' => 'W'));
Friday, September 23, 2011
Database Configuration for MSSQL
If you are connecting to a MSSQL database, first ensure that your php-mssql package is installed. A simple command can show you this:
At this point you can set your database configuration to connect to the database.
Instead, set up a freetds configuration for the server, connect with that instead, and the commands will now work fine.
Edit
$ rpm -qa | grep php-mssqlThe output should look something like this:
php-mssql-5.3.8-4.el6.remi.x86_64Next check that freetds is installed.
$ rpm -qa | grep freetdsThe output should look something like this:
freetds-0.82-6.el6.x86_64You should now be able to connect to your MSSQL database directly from the command line. Make sure to replace the server, user and password with valid information.
$ /usr/bin/tsql -S [mssql.servername.or.ip] -U [ValidUser] locale is "en-US.UTF-8" locale charset is "UTF-8" Password: [password] 1>Enter "quit" to exit your successful connection. If the
tsql
command doesn't return the 1>
prompt, verify that you can get to your MSSQL server with the following command:
ssh [mssql.servername.or.ip] -p 1433Also verify that your username and password are valid.
At this point you can set your database configuration to connect to the database.
var $default = array( 'driver' => 'mssql', 'persistent' => false, 'host' => 'mssql.server.or.ip', 'login' => 'username', 'password' => 'password', 'database' => 'database', 'prefix' => '' );Through much trial and error I've discovered that if you connect directly to the server in this manner some commands, such as
mssql_bind, mssql_execute,
and mssql_init
don't work. Now you could setup and execute stored procedure commands through mssql_query
this isn't as secure.Instead, set up a freetds configuration for the server, connect with that instead, and the commands will now work fine.
Edit
/etc/freetds.conf
and add the following block:
[ServerIdentifier] host = [mssql.servername.or.ip] port = 1433 tds version = 8.0Then use the ServerIdentifier you chose instead of the server name or ip in the database configuration host variable and you're all set.
Monday, September 19, 2011
Multiple Applications, One Cake (or more)
With running multiple CakePHP applications, keeping them all up to date with the latest security fixes can be an issue. Instead of having to update each one individually, having a shared cake installation can be beneficial.
While there are many different methods of doing this, I couldn't get any of the ones I tried to work. So I deconstructed the process and made it VERY simple and functional. Obviously since we are using symlinks this is applicable only on Linux.
Step 1: Extract CakePHP to where you want your application to reside. e.g. /var/www/html/myApp/
Step 2: Extract CakePHP to where you want your Cake to reside. For ease in updating, I named mine the same as the version number. e.g. /var/www/cakephp-1.3.11
Step 3: While unnecessary, I found it convenient to create a symlink to the cake directory named 'cake', otherwise you have to either name your cake folder the same every update, or update all your application symlinks
Step 1: Extract new version of cake to same directory as old version of cake. e.g. /var/www/cakephp-1.3.12
Step 2: Update your shared simple symlink to the new directory
If you want to have an application use an older version of Cake, just install it in the application itself as normal, OR install it next to the other version and change the symlink in the app folder to match the different version of cake.
Step 1: Extract different version of cake for sharing. e.g. /var/www/cakephp-2.0.0-RC2
Step 2: Update your application's symlink to the new directory
While there are many different methods of doing this, I couldn't get any of the ones I tried to work. So I deconstructed the process and made it VERY simple and functional. Obviously since we are using symlinks this is applicable only on Linux.
Step 1: Extract CakePHP to where you want your application to reside. e.g. /var/www/html/myApp/
Step 2: Extract CakePHP to where you want your Cake to reside. For ease in updating, I named mine the same as the version number. e.g. /var/www/cakephp-1.3.11
Step 3: While unnecessary, I found it convenient to create a symlink to the cake directory named 'cake', otherwise you have to either name your cake folder the same every update, or update all your application symlinks
$ ln -s /var/www/cakephp-1.3.11 /var/www/cakeStep 4: Delete the cake directory in your application.
$ rm -fr /var/www/html/myApp/cakeStep 5: Create a symlink in the application folder to the shared cake folder.
$ ln -s /var/www/cake/cake /var/www/html/myApp/cakeNow any application that has that symlink in it instead of the cake folder will use the shared folder. Update the shared folder once, all applications that are sharing it get updated.
Step 1: Extract new version of cake to same directory as old version of cake. e.g. /var/www/cakephp-1.3.12
Step 2: Update your shared simple symlink to the new directory
$ ln -f -s /var/www/cakephp-1.3.12 /var/www/cakeThat easy.
If you want to have an application use an older version of Cake, just install it in the application itself as normal, OR install it next to the other version and change the symlink in the app folder to match the different version of cake.
Step 1: Extract different version of cake for sharing. e.g. /var/www/cakephp-2.0.0-RC2
Step 2: Update your application's symlink to the new directory
$ ln -f -s /var/www/cakephp-2.0.0-RC2/cake /var/www/html/my2.0App/cake
Labels:
cakephp,
installation,
multiple applications
Tuesday, September 13, 2011
Database Configuration for Oracle
If you are connecting to an Oracle database, first ensure that your php_oci8 extension is installed. A simple php page can show you this:
\n";
while (($row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) != false) {
echo "
';
?>
Now that you know you can access your Oracle database via php, configure your CakePHP connection. Edit
<?php phpinfo(); ?>View the page and you should see a heading "OCI8" and it should tell you the version and if it is enabled. Next ensure you can talk to the database. Another simple php file can do this for you. This page will list all tables in the database (code from Oracle's website)
<?php $conn = oci_connect('username', 'password', 'host/database'); $stid = oci_parse($conn, 'select table_name from user_tables'); oci_execute($stid); echo "
'.($item !== null ? htmlentities($item, ENT_QUOTES) : ' ')." | \n"; } echo "
/app/config/database.php
var $default = array( 'driver' => 'oracle', 'connect' => 'oci_connect', 'persistent' => false, 'host' => 'host', 'port' => 1521, 'login' => 'username', 'password' => 'password', 'database' => 'host:1521/database', 'prefix' => '', );And that's all there is to it.
Monday, August 8, 2011
Reset Forgotten Password
For a secure application one issue that will arise repeatedly is users forgetting their passwords. One method of correcting this is to allow users to reset their passwords by submitting their email address. Since the new password will be only be sent to a valid email address, only the appropriate user will know the new password.
For applications open to the public this method is not advised since anyone could possibly find a valid user email address and spam them with reset passwords.
First create the form
Lastly, ensure that you allow access to the
For applications open to the public this method is not advised since anyone could possibly find a valid user email address and spam them with reset passwords.
First create the form
/app/views/users/forgot.ctp
<h2>Forgot Password</h2> <p>Submit your email address and a new password will be emailed to you.</p> <?php echo $form->create('User'); echo $form->input('email'); echo $form->end('Send Password'); ?> <script type="text/javascript"> document.getElementById('UserEmail').focus() </script>Next edit your Users controller at
/app/controllers/users_controller.php
and add the forgot
function.
function forgot(){ if(!empty($this->data)){ $user = $this->User->findByEmail($this->data['User']['email']); if($user){ $user['User']['password'] = $this->__generatePassword(); // Since my users model requires a confirm_password to match the password on update, it is required here // See http://drug-ed.blogspot.com/2011/08/authentication-and-passwords.html $user['User']['confirm_password'] = $user['User']['password']; if ($this->__sendEmail($user['User']['email'], 'New Password', $user['User'], 'newpass')) { if ($this->User->save($user['User'], array('fieldList' => array('password')))) { $this->Session->setFlash(__('An email has been sent with your new password.', true)); $this->redirect(array('action' => 'login')); } else { $this->Session->setFlash(__('The password cound not be saved. Please try again.', true)); } } else { $this->Session->setFlash(__('The email could not be sent. Please try again.', true)); } } else { $this->Session->setFlash('User could not be found.'); } } }My
__sendEmail()
function above is described in detail here.
Here is my __generatePassword
function. Feel free to use it or create your own.
function __generatePassword($length = 8){ $characters = 'abcdefghijklmnpqrstuvwxyz'; $numbers = '123456789'; // No 0 or O so as not to confuse $more = '!@#$%^&_+=-'; $password = ''; $alt = time(); for($i = 0; $i <= $length; $i++){ $alt += rand() % 10; if($alt % 3 == 1){ if($alt % 2 == 1){ $password .= strtoupper($characters[(rand() % strlen($characters))]); } else { $password .= $characters[(rand() % strlen($characters))]; } } elseif($alt % 3 == 2){ $password .= $numbers[(rand() % strlen($numbers))]; } else { $password .= $more[(rand() % strlen($more))]; } } return $password; }Lastly, create your email templates. They can be quite simple.
/app/views/elements/email/text/newpass.ctp
A new password has been requested for the account: <?php echo $data['username'].'.'.PHP_EOL.PHP_EOL; ?> Your new password is: <?php echo $data['password'].PHP_EOL.PHP_EOL; ?> Please use this password to log in, then you can change your password by clicking "Change Password."Since the email is sent before saving, the password isn't hashed yet and will be visible to the user.
Lastly, ensure that you allow access to the
/users/forgot
view by editing /app/app_controller.php
and add 'forgot'
to your $this->Auth->allow()
line.
Friday, August 5, 2011
Sending Email
Sending email in CakePHP is quite simple, however, it can be simpler, especially if you want to follow the DRY methodology.
In the controller you want to send email from simply add the following function:
function __sendEmail($to, $subject, $data, $template, $cc = false){ $this->Email->reset(); $this->Email->from = 'Your Name Here<your@email.here>'; $this->Email->replyTo = 'your@email.here'; $this->Email->additionalParams = '-fyour@email.here'; $this->Email->sendAs = 'both'; $this->Email->template = $template; $this->Email->subject = $subject; $this->Email->to = $to; if($cc) $this->Email->cc = array($cc); $this->set('data', $data); if ($this->Email->send()) { return true; } else { return false; } }Now you can call it with a single line:
$this->__sendEmail('to@email.here', 'Subject', $data, 'templateName', 'cc@email.here'));
Subscribe to:
Posts (Atom)