<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7015944332496215751</id><updated>2024-11-01T04:10:40.490-07:00</updated><category term="model"/><category term="users"/><category term="database"/><category term="controller"/><category term="cakephp"/><category term="configuration"/><category term="auth"/><category term="carriers"/><category term="drugs"/><category term="hasMany"/><category term="layout"/><category term="reminders"/><category term="validation"/><category term="app"/><category term="forms"/><category term="helpers"/><category term="passwords"/><category term="scaffold"/><category term="security"/><category term="about"/><category term="belongsTo"/><category term="compliance"/><category term="components"/><category term="elements"/><category term="email"/><category term="errors"/><category term="freetds"/><category term="hasOne"/><category term="hashing"/><category term="homepage"/><category term="installation"/><category term="javascript"/><category term="mssql"/><category term="multiple applications"/><category term="oracle"/><category term="page title"/><category term="pages"/><category term="pagination"/><category term="radio"/><category term="required"/><category term="routing"/><category term="select"/><category term="style"/><category term="view"/><title type='text'>Medication Adherence</title><subtitle type='html'>Drug Education and Medication Adherence Service developed in CakePHP</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>46</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-2305092571841437122</id><published>2012-07-02T13:35:00.000-07:00</published><updated>2012-07-02T14:46:50.171-07:00</updated><title type='text'>Multi-language Support</title><content type='html'>To allow your application to appear in multiple languages, first change all displayable text to utilize the &lt;code&gt;__()&lt;code&gt; function. For example, for echoed text like the following:
&lt;pre&gt;echo &#39;This text&#39;;&lt;/pre&gt;
Replace it with the following:
&lt;pre&gt;__(&#39;This text&#39;);&lt;/pre&gt;
For variables, such as the following:
&lt;pre&gt;$directions = array(&#39;N&#39; =&gt; &#39;North&#39;, &#39;S&#39; =&gt; &#39;South&#39;, &#39;E&#39; =&gt; &#39;East&#39;, &#39;W&#39; =&gt; &#39;West&#39;);&lt;/pre&gt;
Replace it with the following:
&lt;pre&gt;$directions = array(&#39;N&#39; =&gt; __(&#39;North&#39;, true), &#39;S&#39; =&gt; __(&#39;South&#39;, true), &#39;E&#39; =&gt; __(&#39;East&#39;, true), &#39;W&#39; =&gt; __(&#39;West&#39;, true));&lt;/pre&gt;

Then build your &lt;code&gt;/app/locale/default.pot&lt;/code&gt; file using the console
&lt;pre&gt;# cd /app
# /cake/console/cake i18n extract&lt;/pre&gt;
Accept default options and the file is created.

Edit the &lt;code&gt;/app/locale/default.pot&lt;/code&gt; with a program like Poedit, add your translations, then save the file in the appropriate directory as a catalog (.po file) e.g. &lt;code&gt;/app/locale/spa/LC_MESSAGES/default.po&lt;/code&gt;

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 &lt;code&gt;/app/config/routes.php&lt;/code&gt;:
&lt;pre&gt;  /* For internationalization */
  Router::connect(&#39;/:language/:controller/:action/*&#39;, array(), array(&#39;language&#39; =&gt; &#39;[a-z]{3}&#39;));&lt;/pre&gt;

To specify a default language, add the following to your &lt;code&gt;/app/config/core.php&lt;/code&gt; and add the following lines:
&lt;pre&gt;  /* For internationalization */
  Configure::write(&#39;Config.language&#39;, &#39;eng&#39;);&lt;/pre&gt;

Now to create a language switching link use the following:
&lt;pre&gt;  echo $this-&gt;Html-&gt;link(&#39;Español&#39;, array(&#39;language&#39; =&gt; &#39;spa&#39;));&lt;/pre&gt;

Ensure Cookies and Session components are loaded and put the following functions in the &lt;code&gt;/app/app_controller.php&lt;/code&gt;:
&lt;pre&gt;var $components = array(&#39;Session&#39;, &#39;Cookie&#39;);
 
function beforeFilter() {
  $this-&gt;_setLanguage();
}

function _setLanguage() {
  if ($this-&gt;Cookie-&gt;read(&#39;lang&#39;) &amp;&amp; !$this-&gt;Session-&gt;check(&#39;Config.language&#39;)) {
    $this-&gt;Session-&gt;write(&#39;Config.language&#39;, $this-&gt;Cookie-&gt;read(&#39;lang&#39;));
  }
  else if (isset($this-&gt;params[&#39;language&#39;]) &amp;&amp; ($this-&gt;params[&#39;language&#39;] !=  $this-&gt;Session-&gt;read(&#39;Config.language&#39;))) {
    $this-&gt;Session-&gt;write(&#39;Config.language&#39;, $this-&gt;params[&#39;language&#39;]);
    $this-&gt;Cookie-&gt;write(&#39;lang&#39;, $this-&gt;params[&#39;language&#39;], false, &#39;20 days&#39;);
  }
}&lt;/pre&gt;

Lastly, create the &lt;code&gt;/app/app_helper.php&lt;/code&gt; file
&lt;pre&gt;&lt;?php
class AppHelper extends Helper {
  function url($url = null, $full = false) {
    if(!isset($url[&#39;language&#39;]) &amp;&amp; isset($this-&gt;params[&#39;language&#39;])) {
      $url[&#39;language&#39;] = $this-&gt;params[&#39;language&#39;];
    }
    return parent::url($url, $full);
  }
}
?&gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/2305092571841437122/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2012/07/multi-language-support.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/2305092571841437122'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/2305092571841437122'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2012/07/multi-language-support.html' title='Multi-language Support'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-9061086393507383848</id><published>2012-03-12T15:00:00.005-07:00</published><updated>2012-03-12T16:03:01.809-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="forms"/><category scheme="http://www.blogger.com/atom/ns#" term="helpers"/><category scheme="http://www.blogger.com/atom/ns#" term="radio"/><category scheme="http://www.blogger.com/atom/ns#" term="select"/><title type='text'>Form Helper</title><content type='html'>When using the Form helper to create a form, there are some options you can utilize to make your forms better.

&lt;h4&gt;Radio&lt;/h4&gt;
The following form radio selection is named &#39;Radio name&#39; and lists two options, &#39;label1&#39; and &#39;label2&#39;, with &#39;label1&#39; selected by default.
&lt;pre&gt;echo $this-&gt;Form-&gt;input(&#39;Radio name&#39;, array(&#39;type&#39; =&gt; &#39;radio&#39;, &#39;legend&#39; =&gt; false, &#39;options&#39; =&gt; array(&#39;value1&#39; =&gt; &#39;label1&#39;, &#39;value2&#39; =&gt; &#39;label2&#39;), &#39;default&#39; =&gt; &#39;value1&#39;)); &lt;/pre&gt;

&lt;h4&gt;Selection&lt;/h4&gt;
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.
&lt;pre&gt;$dirs = array(&#39;N&#39; =&gt; &#39;North&#39;, &#39;E&#39; =&gt; &#39;East&#39;, &#39;S&#39; =&gt; &#39;South&#39;, &#39;W&#39; =&gt; &#39;West&#39;);
echo $this-&gt;Form-&gt;input(&#39;street_dir&#39;, array(&#39;label&#39; =&gt; __(&#39;Direction&#39;, true), &#39;type&#39; =&gt; &#39;select&#39;, &#39;options&#39; =&gt; $dirs, &#39;empty&#39; =&gt; true, &#39;default&#39; =&gt; &#39;W&#39;));&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/9061086393507383848/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2012/03/form-helper.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/9061086393507383848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/9061086393507383848'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2012/03/form-helper.html' title='Form Helper'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-5001350781899713661</id><published>2011-09-23T15:41:00.007-07:00</published><updated>2011-09-23T15:56:42.702-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="database"/><category scheme="http://www.blogger.com/atom/ns#" term="freetds"/><category scheme="http://www.blogger.com/atom/ns#" term="mssql"/><title type='text'>Database Configuration for MSSQL</title><content type='html'>If you are connecting to a MSSQL database, first ensure that your php-mssql package is installed. A simple command can show you this:
&lt;pre&gt;$ rpm -qa | grep php-mssql&lt;/pre&gt;
The output should look something like this:
&lt;pre&gt;php-mssql-5.3.8-4.el6.remi.x86_64&lt;/pre&gt;
Next check that freetds is installed.
&lt;pre&gt;$ rpm -qa | grep freetds&lt;/pre&gt;
The output should look something like this:
&lt;pre&gt;freetds-0.82-6.el6.x86_64&lt;/pre&gt;
You 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.
&lt;pre&gt;$ /usr/bin/tsql -S [mssql.servername.or.ip] -U [ValidUser]
locale is &quot;en-US.UTF-8&quot;
locale charset is &quot;UTF-8&quot;
Password: [password]
1&amp;gt;&lt;/pre&gt;
Enter &quot;quit&quot; to exit your successful connection. If the &lt;code&gt;tsql&lt;/code&gt; command doesn&#39;t return the &lt;code&gt;1&amp;gt;&lt;/code&gt; prompt, verify that you can get to your MSSQL server with the following command:
&lt;pre&gt;ssh [mssql.servername.or.ip] -p 1433&lt;/pre&gt;
Also verify that your username and password are valid.
&lt;br /&gt;
At this point you can set your database configuration to connect to the database.
&lt;pre&gt;&amp;nbsp; &amp;nbsp; var $default = array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;driver&#39; =&amp;gt; &#39;mssql&#39;,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;persistent&#39; =&amp;gt; false,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;host&#39; =&amp;gt; &#39;mssql.server.or.ip&#39;,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;login&#39; =&amp;gt; &#39;username&#39;,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;password&#39; =&amp;gt; &#39;password&#39;,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;database&#39; =&amp;gt; &#39;database&#39;,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;prefix&#39; =&amp;gt; &#39;&#39;
&amp;nbsp; &amp;nbsp; );&lt;/pre&gt;
Through much trial and error I&#39;ve discovered that if you connect directly to the server in this manner some commands, such as &lt;code&gt;mssql_bind, mssql_execute,&lt;/code&gt; and &lt;code&gt;mssql_init&lt;/code&gt; don&#39;t work. Now you could setup and execute stored procedure commands through &lt;code&gt;mssql_query&lt;/code&gt; this isn&#39;t as secure.&lt;br /&gt;
Instead, set up a freetds configuration for the server, connect with that instead, and the commands will now work fine.&lt;br /&gt;
Edit &lt;code&gt;/etc/freetds.conf&lt;/code&gt; and add the following block:
&lt;pre&gt;[ServerIdentifier]
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; host = [mssql.servername.or.ip]
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; port = 1433
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; tds version = 8.0&lt;/pre&gt;
Then use the ServerIdentifier you chose instead of the server name or ip in the database configuration host variable and you&#39;re all set.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/5001350781899713661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2011/09/database-configuration-for-mssql.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/5001350781899713661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/5001350781899713661'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2011/09/database-configuration-for-mssql.html' title='Database Configuration for MSSQL'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-6836052680925829420</id><published>2011-09-19T21:24:00.007-07:00</published><updated>2011-09-19T21:55:38.765-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cakephp"/><category scheme="http://www.blogger.com/atom/ns#" term="installation"/><category scheme="http://www.blogger.com/atom/ns#" term="multiple applications"/><title type='text'>Multiple Applications, One Cake (or more)</title><content type='html'>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.&lt;br /&gt;
&lt;br /&gt;
While there are many different methods of doing this, I couldn&#39;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.&lt;br /&gt;
&lt;br /&gt;
Step 1: Extract CakePHP to where you want your application to reside. e.g. /var/www/html/myApp/&lt;br /&gt;
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&lt;br /&gt;
Step 3: While unnecessary, I found it convenient to create a symlink to the cake directory named &#39;cake&#39;, otherwise you have to either name your cake folder the same every update, or update all your application symlinks &lt;pre&gt;$ ln -s /var/www/cakephp-1.3.11 /var/www/cake&lt;/pre&gt;
Step 4: Delete the cake directory in your application. &lt;pre&gt;$ rm -fr /var/www/html/myApp/cake&lt;/pre&gt;
Step 5: Create a symlink in the application folder to the shared cake folder. &lt;pre&gt;$ ln -s /var/www/cake/cake /var/www/html/myApp/cake&lt;/pre&gt;

Now 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.&lt;br /&gt;
Step 1: Extract new version of cake to same directory as old version of cake. e.g. /var/www/cakephp-1.3.12&lt;br /&gt;
Step 2: Update your shared simple symlink to the new directory &lt;pre&gt;$ ln -f -s /var/www/cakephp-1.3.12 /var/www/cake&lt;/pre&gt;
That easy.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
Step 1: Extract different version of cake for sharing. e.g. /var/www/cakephp-2.0.0-RC2&lt;br /&gt;
Step 2: Update your application&#39;s symlink to the new directory &lt;pre&gt;$ ln -f -s /var/www/cakephp-2.0.0-RC2/cake /var/www/html/my2.0App/cake&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/6836052680925829420/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2011/09/multiple-applications-one-cake-or-more.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/6836052680925829420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/6836052680925829420'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2011/09/multiple-applications-one-cake-or-more.html' title='Multiple Applications, One Cake (or more)'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-1092470971174747812</id><published>2011-09-13T14:41:00.003-07:00</published><updated>2011-09-13T14:51:04.811-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="database"/><category scheme="http://www.blogger.com/atom/ns#" term="oracle"/><title type='text'>Database Configuration for Oracle</title><content type='html'>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:
&lt;pre&gt;&amp;lt;?php
  phpinfo();
?&amp;gt;&lt;/pre&gt;
View the page and you should see a heading &quot;OCI8&quot; 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&#39;s website)
&lt;pre&gt;&amp;lt;?php
  $conn = oci_connect(&#39;username&#39;, &#39;password&#39;, &#39;host/database&#39;);
  $stid = oci_parse($conn, &#39;select table_name from user_tables&#39;);
  oci_execute($stid);
  echo &quot;&lt;table&gt;\n&quot;;
  while (($row = oci_fetch_array($stid, OCI_ASSOC+OCI_RETURN_NULLS)) != false) {
    echo &quot;&lt;tr&gt;\n&quot;;
    foreach ($row as $item) {
      echo &#39;  &lt;td&gt;&#39;.($item !== null ? htmlentities($item, ENT_QUOTES) : &#39;&amp;nbsp;&#39;).&quot;&lt;/td&gt;\n&quot;;
    }
    echo &quot;&lt;/tr&gt;\n&quot;;
  }
  echo &#39;&lt;/table&gt;&#39;;
?&amp;gt;&lt;/pre&gt;

Now that you know you can access your Oracle database via php, configure your CakePHP connection. Edit &lt;code&gt;/app/config/database.php&lt;/code&gt;
&lt;pre&gt;var $default = array(
  &#39;driver&#39; =&gt; &#39;oracle&#39;,
  &#39;connect&#39; =&gt; &#39;oci_connect&#39;,
  &#39;persistent&#39; =&gt; false,
  &#39;host&#39; =&gt; &#39;host&#39;,
  &#39;port&#39; =&gt; 1521,
  &#39;login&#39; =&gt; &#39;username&#39;,
  &#39;password&#39; =&gt; &#39;password&#39;,
  &#39;database&#39; =&gt; &#39;host:1521/database&#39;,
  &#39;prefix&#39; =&gt; &#39;&#39;,
);&lt;/pre&gt;

And that&#39;s all there is to it.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/1092470971174747812/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2011/09/database-configuration-for-oracle.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/1092470971174747812'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/1092470971174747812'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2011/09/database-configuration-for-oracle.html' title='Database Configuration for Oracle'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-5967839478446550327</id><published>2011-08-08T11:35:00.008-07:00</published><updated>2011-08-10T15:21:18.306-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="auth"/><category scheme="http://www.blogger.com/atom/ns#" term="passwords"/><title type='text'>Reset Forgotten Password</title><content type='html'>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.
&lt;br /&gt;&lt;br /&gt;
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.
&lt;br /&gt;&lt;br /&gt;
First create the form &lt;code&gt;/app/views/users/forgot.ctp&lt;/code&gt;
&lt;pre&gt;&amp;lt;h2&amp;gt;Forgot Password&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Submit your email address and a new password will be emailed to you.&amp;lt;/p&amp;gt;
&amp;lt;?php
&amp;nbsp; &amp;nbsp; echo $form-&amp;gt;create(&#39;User&#39;);
&amp;nbsp; &amp;nbsp; echo $form-&amp;gt;input(&#39;email&#39;);
&amp;nbsp; &amp;nbsp; echo $form-&amp;gt;end(&#39;Send Password&#39;);
?&amp;gt;
&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
document.getElementById(&#39;UserEmail&#39;).focus()
&amp;lt;/script&amp;gt;&lt;/pre&gt;
Next edit your Users controller at &lt;code&gt;/app/controllers/users_controller.php&lt;/code&gt; and add the &lt;code&gt;forgot&lt;/code&gt; function.
&lt;pre&gt;&amp;nbsp; &amp;nbsp; function forgot(){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if(!empty($this-&amp;gt;data)){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $user = $this-&amp;gt;User-&amp;gt;findByEmail($this-&amp;gt;data[&#39;User&#39;][&#39;email&#39;]);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if($user){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $user[&#39;User&#39;][&#39;password&#39;] = $this-&amp;gt;__generatePassword();
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Since my users model requires a confirm_password to match the password on update, it is required here
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // See http://drug-ed.blogspot.com/2011/08/authentication-and-passwords.html
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $user[&#39;User&#39;][&#39;confirm_password&#39;] = $user[&#39;User&#39;][&#39;password&#39;];
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if ($this-&amp;gt;__sendEmail($user[&#39;User&#39;][&#39;email&#39;], &#39;New Password&#39;, $user[&#39;User&#39;], &#39;newpass&#39;)) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if ($this-&amp;gt;User-&amp;gt;save($user[&#39;User&#39;], array(&#39;fieldList&#39; =&amp;gt; array(&#39;password&#39;)))) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;Session-&amp;gt;setFlash(__(&#39;An email has been sent with your new password.&#39;, true));
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;redirect(array(&#39;action&#39; =&amp;gt; &#39;login&#39;));
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; } else {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;Session-&amp;gt;setFlash(__(&#39;The password cound not be saved. Please try again.&#39;, true));
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; } else {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;Session-&amp;gt;setFlash(__(&#39;The email could not be sent. Please try again.&#39;, true));
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; } else {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;Session-&amp;gt;setFlash(&#39;User could not be found.&#39;);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
My &lt;code&gt;__sendEmail()&lt;/code&gt; function above is described in detail &lt;a href=&quot;/2011/08/sending-email.html&quot;&gt;here&lt;/a&gt;.
Here is my &lt;code&gt;__generatePassword&lt;/code&gt; function. Feel free to use it or create your own.
&lt;pre&gt;&amp;nbsp; &amp;nbsp; function __generatePassword($length = 8){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $characters = &#39;abcdefghijklmnpqrstuvwxyz&#39;;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $numbers = &#39;123456789&#39;; // No 0 or O so as not to confuse
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $more = &#39;!@#$%^&amp;_+=-&#39;;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $password = &#39;&#39;;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $alt = time();
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for($i = 0; $i &amp;lt;= $length; $i++){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $alt += rand() % 10;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if($alt % 3 == 1){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if($alt % 2 == 1){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $password .= strtoupper($characters[(rand() % strlen($characters))]);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; } else {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $password .= $characters[(rand() % strlen($characters))];
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; } elseif($alt % 3 == 2){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $password .= $numbers[(rand() % strlen($numbers))];&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; } else {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $password .= $more[(rand() % strlen($more))];&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return $password;
&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
Lastly, create your email templates. They can be quite simple. &lt;code&gt;/app/views/elements/email/text/newpass.ctp&lt;/code&gt;
&lt;pre&gt;A new password has been requested for the account: &amp;lt;?php echo $data[&#39;username&#39;].&#39;.&#39;.PHP_EOL.PHP_EOL; ?&amp;gt;
Your new password is: &amp;lt;?php echo $data[&#39;password&#39;].PHP_EOL.PHP_EOL; ?&amp;gt;
Please use this password to log in, then you can change your password by clicking &quot;Change Password.&quot;&lt;/pre&gt;
Since the email is sent before saving, the password isn&#39;t hashed yet and will be visible to the user.
&lt;br /&gt;&lt;br /&gt;
Lastly, ensure that you allow access to the &lt;code&gt;/users/forgot&lt;/code&gt; view by editing &lt;code&gt;/app/app_controller.php&lt;/code&gt; and add &lt;code&gt;&#39;forgot&#39;&lt;/code&gt; to your &lt;code&gt;$this-&gt;Auth-&gt;allow()&lt;/code&gt; line.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/5967839478446550327/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2011/08/reset-forgotten-password_08.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/5967839478446550327'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/5967839478446550327'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2011/08/reset-forgotten-password_08.html' title='Reset Forgotten Password'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-4398048009033347252</id><published>2011-08-05T17:31:00.004-07:00</published><updated>2011-08-05T17:38:06.129-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="email"/><title type='text'>Sending Email</title><content type='html'>Sending email in CakePHP is quite simple, however, it can be simpler, especially if you want to follow the &lt;acronym title=&quot;Don&#39;t Repeat Yourself&quot;&gt;DRY&lt;/acronym&gt; methodology.

In the controller you want to send email from simply add the following function:
&lt;pre&gt;&amp;nbsp; &amp;nbsp; function __sendEmail($to, $subject, $data, $template, $cc = false){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;Email-&amp;gt;reset();
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;Email-&amp;gt;from = &#39;Your Name Here&amp;lt;your@email.here&amp;gt;&#39;;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;Email-&amp;gt;replyTo = &#39;your@email.here&#39;;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;Email-&amp;gt;additionalParams = &#39;-fyour@email.here&#39;;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;Email-&amp;gt;sendAs = &#39;both&#39;;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;Email-&amp;gt;template = $template;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;Email-&amp;gt;subject = $subject;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;Email-&amp;gt;to = $to;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if($cc) $this-&amp;gt;Email-&amp;gt;cc = array($cc);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;set(&#39;data&#39;, $data);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if ($this-&amp;gt;Email-&amp;gt;send()) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return true;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; } else {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return false;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp; 
&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
Now you can call it with a single line:
&lt;pre&gt;$this-&amp;gt;__sendEmail(&#39;to@email.here&#39;, &#39;Subject&#39;, $data, &#39;templateName&#39;, &#39;cc@email.here&#39;));&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/4398048009033347252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2011/08/sending-email.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/4398048009033347252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/4398048009033347252'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2011/08/sending-email.html' title='Sending Email'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-2504687785517702017</id><published>2011-08-03T10:47:00.003-07:00</published><updated>2011-08-03T10:50:23.856-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="validation"/><title type='text'>More Validation Tips and Tricks</title><content type='html'>A good shortcut when creating Validation rules is to use the desired message as the key name. CakePHP will automatically use the key name as the error message in the absence of an explicit message.
&lt;pre&gt;&amp;nbsp; &amp;nbsp; var $validate = array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;username&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;Username must contain only letters and numbers&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;rule&#39; =&gt; &#39;/^[a-z0-9]{3,}$/i&#39;,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;required&#39; =&gt; true
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;This username is already taken&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;rule&#39; =&gt; &#39;isUnique&#39;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;Username must be at least 5 characters&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;rule&#39; =&gt; array(&#39;minlength&#39;, 5),
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ) 
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )
&amp;nbsp; &amp;nbsp; );&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/2504687785517702017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2011/08/more-validation-tips-and-tricks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/2504687785517702017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/2504687785517702017'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2011/08/more-validation-tips-and-tricks.html' title='More Validation Tips and Tricks'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-1600138343934662904</id><published>2011-08-02T17:50:00.007-07:00</published><updated>2011-08-08T12:21:06.680-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="auth"/><category scheme="http://www.blogger.com/atom/ns#" term="hashing"/><category scheme="http://www.blogger.com/atom/ns#" term="passwords"/><title type='text'>Authentication and Passwords</title><content type='html'>One issue that will pop up is trying to add or edit users with Authentication enabled. Validation won&#39;t work properly on the password field because Authentication will hash the password BEFORE it attempts to validate. For example checking for a minimum length will always succeed regardless of the actual password because SHA1 hashed passwords will always be 40 characters.
&lt;br /&gt;&lt;br /&gt;
One method around this is performing the hashing manually. To do this you have to tell your users controller you want to perform your own hashing. Edit &lt;code&gt;/app/controllers/users_controller.php&lt;/code&gt; and add the following function:
&lt;pre&gt;&amp;nbsp; &amp;nbsp; function beforeFilter(){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; parent::beforeFilter();
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if($this-&gt;action == &#39;add&#39; || $this-&gt;action == &#39;edit&#39; || $this-&gt;action == &#39;password&#39;){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&gt;Auth-&gt;authenticate = $this-&gt;User;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;Now when you are using the &lt;code&gt;add&lt;/code&gt; or &lt;code&gt;edit&lt;/code&gt; actions authentication is done manually. You&#39;ll see why the action &lt;code&gt;password&lt;/code&gt; is in there later.
&lt;br /&gt;
Next edit the users model &lt;code&gt;/app/model/users.php&lt;/code&gt; and add the following functions:
&lt;pre&gt;&amp;nbsp; &amp;nbsp; function hashPasswords($data, $enforce=false) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if($enforce &amp;&amp; isset($this-&gt;data[$this-&gt;alias][&#39;password&#39;])) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if(!empty($this-&gt;data[$this-&gt;alias][&#39;password&#39;])) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&gt;data[$this-&gt;alias][&#39;password&#39;] = Security::hash($this-&gt;data[$this-&gt;alias][&#39;password&#39;], null, true);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return $data;
&amp;nbsp; &amp;nbsp; }

&amp;nbsp; &amp;nbsp; function beforeSave() {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&gt;hashPasswords(null, true);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return true;
&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;Now your users model will hash the passwords before save, allowing validation to take place first.
&lt;br /&gt;&lt;br /&gt;
Another problem, however, is when editing a user, the hashed password is used in the password field of the form and becomes hashed again on save, actually changing the password! I&#39;m surprised this issue isn&#39;t addressed in the core of CakePHP.
&lt;br /&gt;&lt;br /&gt;
One way around this is to modify your edit view to clear the password field of the hashed password. Edit &lt;code&gt;/app/views/users/edit.ctp&lt;/code&gt; and change this
&lt;pre&gt;&amp;nbsp; &amp;nbsp; echo $this-&gt;Form-&gt;input(&#39;password&#39;);&lt;/pre&gt; to this
&lt;pre&gt;&amp;nbsp; &amp;nbsp; echo $this-&gt;Form-&gt;input(&#39;password&#39;, array(&#39;value&#39; =&gt; &#39;&#39;));&lt;/pre&gt; This will require you to enter a password every time you edit the user because your validation is set to require 5 characters in the password field.
&lt;br /&gt;&lt;br /&gt;
So to get around that simply remove the &lt;code&gt;password&lt;/code&gt; field from your edit form. You can also remove the &lt;code&gt;edit&lt;/code&gt; action from your &lt;code&gt;beforeFilter&lt;/code&gt; function in the users controller. Now you can edit the user without worrying about the password.
&lt;br /&gt;&lt;br /&gt;
Then, to edit the password create a &lt;code&gt;password&lt;/code&gt; function in your controller and a separate view. Edit &lt;code&gt;/app/controllers/users_controller.php&lt;/code&gt; and add this function:
&lt;pre&gt;&amp;nbsp; &amp;nbsp; function password($id = null){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /* Only edit own account unless admin */
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if(!$this-&gt;Auth-&gt;user(&#39;admin&#39;)){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $id = $this-&gt;Auth-&gt;user(&#39;id&#39;);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&amp;nbsp; &amp;nbsp; 
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (!$id &amp;&amp; empty($this-&gt;data)) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&gt;Session-&gt;setFlash(__(&#39;Invalid user&#39;, true));
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&gt;redirect(array(&#39;action&#39; =&gt; &#39;index&#39;));
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (!empty($this-&gt;data)) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if ($this-&gt;User-&gt;save($this-&gt;data, array(&#39;fieldList&#39; =&gt; array(&#39;password&#39;)))) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&gt;Session-&gt;setFlash(__(&#39;The password has been saved&#39;, true));
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&gt;redirect(array(&#39;action&#39; =&gt; &#39;index&#39;));
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; } else {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&gt;Session-&gt;setFlash(__(&#39;The password could not be saved. Please, try again.&#39;, true));
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (empty($this-&gt;data)) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&gt;data = $this-&gt;User-&gt;read(null, $id);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /* Don&#39;t display current hashed password */
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&gt;data[&#39;User&#39;][&#39;password&#39;] = &#39;&#39;;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
Now create &lt;code&gt;/app/views/users/password.ctp&lt;/code&gt;
&lt;pre&gt;&amp;lt;div class=&quot;users form&quot;&amp;gt; 
&amp;lt;?php echo $this-&amp;gt;Form-&amp;gt;create(&#39;User&#39;); ?&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;fieldset&amp;gt;&amp;lt;legend&amp;gt;Change Password&amp;lt;/legend&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;?php
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; echo $this-&amp;gt;Form-&amp;gt;hidden(&#39;id&#39;);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; echo $this-&amp;gt;Form-&amp;gt;input(&#39;password&#39;, array(&#39;label&#39; =&amp;gt; &#39;New Password&#39;));
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; echo $this-&amp;gt;Form-&amp;gt;input(&#39;confirm_password&#39;, array(&#39;type&#39; =&amp;gt; &#39;password&#39;));
&amp;nbsp; &amp;nbsp; ?&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;/fieldset&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;?php echo $this-&amp;gt;Form-&amp;gt;end(&#39;Save Password&#39;); ?&amp;gt;
&amp;lt;/div&amp;gt;&lt;/pre&gt;
Then modify your users model &lt;code&gt;/app/models/user.php&lt;/code&gt; and add the following validation rules and functions:
&lt;pre&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;password&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;Your password must be at least 5 characters&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;rule&#39; =&gt; array(&#39;minlength&#39;, 5)
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;You must enter the same password twice&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;rule&#39; =&gt; array(&#39;matchPasswords&#39;, &#39;confirm_password&#39;),
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;on&#39; =&gt; &#39;update&#39;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;confirm_password&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;rule&#39; =&gt; &#39;notEmpty&#39;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )

&amp;nbsp; &amp;nbsp; function matchPasswords($data, $confirm_password){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if ($data[&#39;password&#39;] != $this-&gt;data[$this-&gt;alias][$confirm_password]) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&gt;invalidate($confirm_password, &#39;You must enter the same password twice&#39;);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return false;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return true;
&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;Set appropriate authentication as desired, upload the files and you should be all set.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/1600138343934662904/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2011/08/authentication-and-passwords.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/1600138343934662904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/1600138343934662904'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2011/08/authentication-and-passwords.html' title='Authentication and Passwords'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-5913438981491020942</id><published>2011-07-25T13:04:00.004-07:00</published><updated>2011-08-08T12:21:24.159-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="database"/><category scheme="http://www.blogger.com/atom/ns#" term="errors"/><title type='text'>Log Database Errors</title><content type='html'>First read here: &lt;a href=&quot;http://nuts-and-bolts-of-cakephp.com/2010/10/31/catch-database-errors-before-its-too-late/&quot;&gt;Catch database errors before it’s too late&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
It&#39;s as simple as adding an &lt;code&gt;onError&lt;/code&gt; function to your &lt;code&gt;app_model.php&lt;/code&gt; file, and whenever there is a database error, the error in the database will be logged in your CakePHP log.
&lt;br /&gt;&lt;br /&gt;
Edit &lt;code&gt;/app/app_model.php&lt;/code&gt; and add the following function:
&lt;pre&gt;&amp;nbsp; &amp;nbsp; public function onError() {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $db = ConnectionManager::getDataSource(&#39;default&#39;);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $err = $db-&gt;lastError();
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&gt;log($err);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&gt;log($this-&gt;data);
&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/5913438981491020942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2011/07/log-database-errors.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/5913438981491020942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/5913438981491020942'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2011/07/log-database-errors.html' title='Log Database Errors'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-4751666877292334162</id><published>2011-07-25T12:42:00.003-07:00</published><updated>2011-08-08T12:21:28.260-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="components"/><category scheme="http://www.blogger.com/atom/ns#" term="security"/><title type='text'>Simple Form Security</title><content type='html'>First read this post: &lt;a href=&quot;http://nuts-and-bolts-of-cakephp.com/2008/11/05/make-your-cakephp-forms-a-lot-more-secure/&quot;&gt;Make your CakePHP forms a lot more secure&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
The nuts and bolts of it is that by simply adding the &lt;code&gt;Security&lt;/code&gt; component, it will automatically add a hash to all your forms and if someone tries modifying your form, it won&#39;t work.
&lt;br /&gt;&lt;br /&gt;
And you can implment it as easy as this: Edit &lt;code&gt;/app/app_controller.php&lt;/code&gt; and change the &lt;code&gt;var $components&lt;/code&gt; line to include &lt;code&gt;Security&lt;/code&gt; like this: &lt;pre&gt;&amp;nbsp; &amp;nbsp; var $components = array(&#39;Auth&#39;, &#39;Security&#39;, &#39;Session&#39;);&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/4751666877292334162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2011/07/simple-form-security.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/4751666877292334162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/4751666877292334162'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2011/07/simple-form-security.html' title='Simple Form Security'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-9111644715845454283</id><published>2011-07-25T12:20:00.004-07:00</published><updated>2011-08-08T12:21:33.541-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="layout"/><category scheme="http://www.blogger.com/atom/ns#" term="style"/><title type='text'>Stylesheets and Print Stylesheet</title><content type='html'>Adding a stylesheet to your site is as simple as changing the &lt;a href=&quot;/2010/11/layout-default.html&quot;&gt;default layout&lt;/a&gt;.
&lt;br /&gt;&lt;br /&gt;
Open &lt;code&gt;/app/views/layouts/default.ctp&lt;/code&gt; and within the first 10 lines of the page is the line &lt;pre&gt;echo $this-&gt;Html-&gt;css(&#39;cake.generic&#39;);&lt;/pre&gt; Cake comes with a default style in &lt;code&gt;/app/webroot/css/cake.generic.css&lt;/code&gt; which you can edit until your heart&#39;s content. Or you can create your own stylesheet and put it into the same folder and change that line to direct your pages to the new style. Observe how the &lt;code&gt;.css&lt;/code&gt; extension is not included in the cake function call.
&lt;br /&gt;&lt;br /&gt;
For a Print Stylesheet, it is a little different. To set a print stylesheet you need to set the options to include the media type.
&lt;pre&gt;echo $this-&gt;Html-&gt;css(&#39;cake.print&#39;, &#39;stylesheet&#39;, array(&#39;media&#39; =&gt; &#39;print&#39;));&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/9111644715845454283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2011/07/stylesheets-and-print-stylesheet.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/9111644715845454283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/9111644715845454283'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2011/07/stylesheets-and-print-stylesheet.html' title='Stylesheets and Print Stylesheet'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-6196109856550388056</id><published>2011-07-14T09:58:00.005-07:00</published><updated>2011-08-03T12:06:30.514-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="required"/><category scheme="http://www.blogger.com/atom/ns#" term="validation"/><title type='text'>Validation Tips and Tricks</title><content type='html'>When using validation, as mentioned &lt;a href=&quot;/2010/11/validate-model-user.html&quot;&gt;previously&lt;/a&gt;, there are some tricks to automatically adding the class &lt;code&gt;required&lt;/code&gt; to your form fields. Any validation rule that has &lt;code&gt;minlength&lt;/code&gt; works. So a short, simple rule to just ensure the required class is added to the field label could look something like this:
&lt;pre&gt;&amp;nbsp; &amp;nbsp; var $validate = array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;field_name&#39; =&amp;gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;rule&#39; =&amp;gt; array(&#39;minlength&#39;, 1)
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )
&amp;nbsp; &amp;nbsp; );&lt;/pre&gt;
If you want to require user input but don&#39;t care about the &lt;code&gt;required&lt;/code&gt; class for your labels, you can actually use something as simple as this:
&lt;pre&gt;&amp;nbsp; &amp;nbsp; var $validate = array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;field_name&#39; =&amp;gt; &#39;notEmpty&#39;
&amp;nbsp; &amp;nbsp; );&lt;/pre&gt;
If you expand that to the following code, however, you will also get the &lt;code&gt;required&lt;/code&gt; class for your field label.
&lt;pre&gt;&amp;nbsp; &amp;nbsp; var $validate = array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;field_name&#39; =&amp;gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;rule&#39; =&amp;gt; &#39;notEmpty&#39;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )
&amp;nbsp; &amp;nbsp; );&lt;/pre&gt;
This is very useful when you want the &lt;code&gt;required&lt;/code&gt; class for select fields.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/6196109856550388056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2011/07/validation-tips-and-tricks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/6196109856550388056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/6196109856550388056'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2011/07/validation-tips-and-tricks.html' title='Validation Tips and Tricks'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-1513619498254811927</id><published>2011-07-13T17:18:00.006-07:00</published><updated>2011-08-08T12:23:36.024-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="model"/><category scheme="http://www.blogger.com/atom/ns#" term="users"/><title type='text'>Model: User: Display Name</title><content type='html'>When adding a record that has a relationship of &quot;belongs to&quot; with another table as mentioned &lt;a href=&quot;/2010/11/model-reminder.html&quot;&gt;previously&lt;/a&gt;, CakePHP automatically lists the records of the other table using the display name of that model. By default that display name field is &quot;name&quot;. However, if your field doesn&#39;t have a &quot;name&quot; field, such as the Users table, you can specify the display name manually in the model.
&lt;br /&gt;&lt;br /&gt;
Edit &lt;code&gt;app/models/user.php&lt;/code&gt; and add the following line:
&lt;pre&gt;&amp;nbsp; &amp;nbsp; var $displayField = &#39;username&#39;;&lt;/pre&gt;
This does not support multiple fields, for example if you wanted to combine &lt;code&gt;first_name&lt;/code&gt; and &lt;code&gt;last_name&lt;/code&gt;. In order to do this you need to use &lt;code&gt;virtualFields&lt;/code&gt; in your model. Virtual fields allow you to access a created field, but you cannot save it.
&lt;br /&gt;&lt;br /&gt;
Edit &lt;code&gt;app/models/user.php&lt;/code&gt; and add the following line:
&lt;pre&gt;&amp;nbsp; &amp;nbsp; var $virtualFields = array( &#39;full_name&#39; =&amp;gt; &quot;CONCAT(User.first_name, &#39; &#39;, User.last_name)&quot;);&lt;/pre&gt; then change the display field from &lt;code&gt;username&lt;/code&gt; to &lt;code&gt;full_name&lt;/code&gt;.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/1513619498254811927/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2011/07/model-user-display-name.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/1513619498254811927'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/1513619498254811927'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2011/07/model-user-display-name.html' title='Model: User: Display Name'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-4277761221865011566</id><published>2010-11-10T17:44:00.007-07:00</published><updated>2011-08-08T12:23:31.548-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="controller"/><category scheme="http://www.blogger.com/atom/ns#" term="homepage"/><title type='text'>Home Page</title><content type='html'>While you can route your home page to a controller and action as we did &lt;a href=&quot;/2010/11/routing.html&quot;&gt;previously&lt;/a&gt;, you may prefer to have a separate page set up as the leading page into your site. A good practice is to create a homepage controller and view to use as the main page to your site, this way all of the other controllers and views are tied specifically and only to the model to which they belong.
&lt;br /&gt;&lt;br /&gt;
First create &lt;code&gt;/app/controllers/homepages_controller.php&lt;/code&gt;
&lt;pre&gt;&amp;lt;?php
class HomepagesController extends AppController {

}
?&amp;gt;&lt;/pre&gt;Since the home page controller does not have an associated model, if we wanted to access any data we would define the models we want to access with the &lt;code&gt;$uses&lt;/code&gt; variable. If the models are associated, such as our &quot;User&quot; model and &quot;Carrier&quot; model, it may not be necessary to include both, but if they are not related, such as the &quot;Drug&quot; model, but you want to include data from that table, you need to include both.
&lt;pre&gt;var $uses = array(&#39;User&#39;, &#39;Drug&#39;);&lt;/pre&gt;
In our case we won&#39;t be using any data for the home page at this time so we need to create an empty array. We&#39;ll also need to create an &lt;code&gt;index&lt;/code&gt; method.
&lt;pre&gt;var $uses = array();

function index() {
&amp;nbsp; &amp;nbsp; $this-&gt;set(&#39;title_for_layout&#39;, &#39;Drug-Ed.com : Drug Education and Medication Adherence&#39;);
}&lt;/pre&gt;
Next we need to create the home page view so create &lt;code&gt;/app/views/homepages/index.ctp&lt;/code&gt; For now we&#39;ll leave this blank.
&lt;br /&gt;&lt;br /&gt;
And the last thing we need to do is change our routing to go to the home page instead of the &lt;a href=&quot;/2010/11/routing.html&quot;&gt;previously&lt;/a&gt; set up users page.
&lt;br /&gt;&lt;br /&gt;
Edit &lt;code&gt;/app/config/routes.php&lt;/code&gt; and replace
&lt;pre&gt;&amp;nbsp; &amp;nbsp; Router::connect(&#39;/&#39;, array(&#39;controller&#39;=&amp;gt;&#39;users&#39;, &#39;action&#39;=&amp;gt;&#39;index&#39;));&lt;/pre&gt; with &lt;pre&gt;&amp;nbsp; &amp;nbsp; Router::connect(&#39;/&#39;, array(&#39;controller&#39;=&amp;gt;&#39;homepages&#39;, &#39;action&#39;=&amp;gt;&#39;index&#39;));&lt;/pre&gt;
Now browse to &lt;a href=&quot;http://drug-ed.com/&quot;&gt;http://drug-ed.com/&lt;/a&gt; and verify it goes to the homepages index.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/4277761221865011566/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2010/11/home-page.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/4277761221865011566'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/4277761221865011566'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2010/11/home-page.html' title='Home Page'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-3419063784141345076</id><published>2010-11-10T17:00:00.003-07:00</published><updated>2011-08-08T12:23:10.827-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="forms"/><category scheme="http://www.blogger.com/atom/ns#" term="javascript"/><title type='text'>Form Focus</title><content type='html'>One thing I find annoying on web pages is when there is a form you are expected to fill out, such as a login form, and the focus is not on the first field.
&lt;br /&gt;&lt;br /&gt;
Edit &lt;code&gt;/app/views/users/login.ctp&lt;/code&gt; and add to the bottom of the page:
&lt;pre&gt;&amp;lt;script type=&quot;text/javascript&quot;&amp;gt;
document.getElementById(&#39;UserUsername&#39;).focus() 
&amp;lt;/script&amp;gt;&lt;/pre&gt;Save and upload the file then browse to &lt;a href=&quot;http://drug-ed.com/users/login&quot;&gt;http://drug-ed.com/users/login&lt;/a&gt; and verify the username field has focus.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/3419063784141345076/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2010/11/form-focus.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/3419063784141345076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/3419063784141345076'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2010/11/form-focus.html' title='Form Focus'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-1263955204816374391</id><published>2010-11-10T16:17:00.009-07:00</published><updated>2011-08-08T12:23:06.281-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="auth"/><title type='text'>More Authentication</title><content type='html'>While most of the default settings for the Auth component are good enough, there are many things you can add and change to allow more flexibility. If the default setting (as seen in the examples below) is good enough, you don&#39;t need to add the code at all.
&lt;br /&gt;&lt;br /&gt;
By default the Auth component uses the Security class for hashing the password and the Security class uses SHA1 for hashing. The Auth component automatically performs the hashing for password verification and user creation as long as there are both username and password fields.
&lt;br /&gt;&lt;br /&gt;
As mentioned &lt;a href=&quot;/2010/11/authentication.html&quot;&gt;previously&lt;/a&gt;, these settings can go into the specific controllers, or in the app controller for use with all controllers.
&lt;br /&gt;&lt;br /&gt;
You can use change the hashing method for the Security class as follows:
&lt;pre&gt;Security::setHash(&#39;md5&#39;); // or sha256 or sha1 (default)&lt;/pre&gt;
For the error message on invalid login use &lt;code&gt;loginError&lt;/code&gt;.
&lt;pre&gt;$this-&gt;Auth-&gt;loginError = &quot;Login failed. Invalid username or password.&quot;;&lt;/pre&gt;
For the error message when trying to access a protected page use &lt;code&gt;authError&lt;/code&gt;.
&lt;pre&gt;$this-&gt;Auth-&gt;authError = &quot;You are not authorized to access that location.&quot;;&lt;/pre&gt;
While the Auth component remembers what page you were trying to access before logging in, if you enter the site from an external link for example you can set what URL the user goes to after login, you can also set the URL after logout.
&lt;pre&gt;$this-&gt;Auth-&gt;loginRedirect = array(&#39;controller&#39; =&gt; &#39;users&#39;, &#39;action&#39; =&gt; &#39;index&#39;);
$this-&gt;Auth-&gt;logoutRedirect = array(&#39;controller&#39; =&gt; &#39;users&#39;, &#39;action&#39; =&gt; &#39;login&#39;);&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/1263955204816374391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2010/11/more-authentication.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/1263955204816374391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/1263955204816374391'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2010/11/more-authentication.html' title='More Authentication'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-4375276820576784126</id><published>2010-11-10T15:21:00.017-07:00</published><updated>2011-09-26T16:35:47.275-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="app"/><category scheme="http://www.blogger.com/atom/ns#" term="auth"/><category scheme="http://www.blogger.com/atom/ns#" term="users"/><title type='text'>Authentication</title><content type='html'>To set up a user login system for your CakePHP application, Cake comes with an authentication component built in. The Auth component requires a &quot;user&quot; table in the database with at least the fields of &quot;username&quot; and &quot;password&quot;. Though they don&#39;t have to be named exactly that, it makes everything easier.
&lt;br /&gt;&lt;br /&gt;
The first thing you need to do is to add the Auth component to your controllers. Since typically you want all your controllers to utilize the Auth component, it is best to create an App controller and include it in there.
&lt;br /&gt;&lt;br /&gt;
Create &lt;code&gt;/app/app_controller.php&lt;/code&gt;
&lt;pre&gt;&amp;lt;?php
class AppController extends Controller{
&amp;nbsp; &amp;nbsp; var $components = array(&#39;Auth&#39;);
}
?&amp;gt;&lt;/pre&gt;If at any time you encounter trouble with your authentication, comment out this line to turn it off.
&lt;br /&gt;&lt;br /&gt;
&lt;b&gt;NOTE:&lt;/b&gt; When you explicitly define your components, you disable the default components in CakePHP, such as &lt;code&gt;Session&lt;/code&gt; so if you want to use the session component, be sure to explicitly define it in your array.
&lt;pre&gt;&amp;nbsp; &amp;nbsp; var $components = array(&#39;Auth&#39;,&#39;Session&#39;);&lt;/pre&gt;
The next requirement is to have &lt;code&gt;login()&lt;/code&gt; and &lt;code&gt;logout&lt;/code&gt; methods in your users controller.
&lt;br /&gt;&lt;br /&gt;
Exit &lt;code&gt;/app/controllers/users_controller.php&lt;/code&gt; and add the &lt;code&gt;login&lt;/code&gt; and &lt;code&gt;logout&lt;/code&gt; methods as below.
&lt;pre&gt;&amp;nbsp; &amp;nbsp; function login() {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;set(&#39;title_for_layout&#39;, &#39;Login&#39;);
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /* If user is already logged in, redirect */
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if ($this-&amp;gt;Auth-&amp;gt;user()) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;redirect($this-&amp;gt;Auth-&amp;gt;redirect());
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; }

&amp;nbsp; &amp;nbsp; function logout() {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; $this-&amp;gt;redirect($this-&amp;gt;Auth-&amp;gt;logout());
&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
The last requirement is the view for the login action of the users controller.
&lt;br /&gt;&lt;br /&gt;
Create &lt;code&gt;/app/views/users/login.ctp&lt;/code&gt;
&lt;pre&gt;&amp;lt;?php
&amp;nbsp; &amp;nbsp; echo $session-&amp;gt;flash(&#39;auth&#39;);
&amp;nbsp; &amp;nbsp; echo $form-&amp;gt;create(&#39;User&#39;, array(&#39;action&#39; =&amp;gt; &#39;login&#39;));
&amp;nbsp; &amp;nbsp; echo $form-&amp;gt;input(&#39;username&#39;);
&amp;nbsp; &amp;nbsp; echo $form-&amp;gt;input(&#39;password&#39;);
&amp;nbsp; &amp;nbsp; echo $form-&amp;gt;end(&#39;Login&#39;);
?&amp;gt;&lt;/pre&gt;
The login view uses the form helper to create a form allowing entry of the username and password.
&lt;br /&gt;&lt;br /&gt;
In a controller, the &lt;code&gt;beforeFilter()&lt;/code&gt; method is called automatically before any other controller action. This is where you define the settings for your Auth component.
&lt;br /&gt;&lt;br /&gt;
Edit &lt;code&gt;/app/app_controller.php&lt;/code&gt; and add the &lt;code&gt;beforeFilter&lt;/code&gt; method below.
&lt;pre&gt;function beforeFilter() {
&amp;nbsp; &amp;nbsp; /* Set username and password fields if not using default &#39;username&#39; and &#39;password&#39; */
&amp;nbsp; &amp;nbsp; $this-&gt;Auth-&gt;fields = array(&#39;username&#39; =&gt; &#39;email&#39;, &#39;password&#39; =&gt; &#39;password&#39;);
&amp;nbsp; &amp;nbsp; /* What actions are allowed without authentication */
&amp;nbsp; &amp;nbsp; $this-&gt;Auth-&gt;allow(&#39;*&#39;); // Allow all defined methods
}&lt;/pre&gt;By default, the Auth component only allows the &lt;code&gt;login&lt;/code&gt; and &lt;code&gt;logout&lt;/code&gt; methods. Allowing all actions will allow you to create a user and set the password so you will be able to login once you lock the site down.
&lt;br /&gt;&lt;br /&gt;
If you are still using &lt;a href=&quot;/2010/11/controller-carriers.html&quot;&gt;scaffolding &lt;/a&gt;at this point however, scaffold methods are not allowed without being explicitly defined.
&lt;br /&gt;&lt;br /&gt;
Edit &lt;code&gt;/app/app_controller.php&lt;/code&gt; and change the &lt;code&gt;$this-&gt;Auth-&gt;allow()&lt;/code&gt; command as follows:
&lt;pre&gt;&amp;nbsp; &amp;nbsp; $this-&gt;Auth-&gt;allow(&#39;*&#39;, &#39;add&#39;);&lt;/pre&gt;
Browse to &lt;a href=&quot;http://drug-ed.com/users/add/&quot;&gt;http://drug-ed.com/users/add/&lt;/a&gt; and create a new user with a properly &lt;a href=&quot;/2010/11/more-authentication.html&quot;&gt;hashed&lt;/a&gt; password so you can login.
&lt;br /&gt;&lt;br /&gt;
Edit &lt;code&gt;/app/app_controller.php&lt;/code&gt; and comment out the &lt;code&gt;$this-&gt;Auth-&gt;allow()&lt;/code&gt; command to prevent all access to the site unless signed in. Browse to any page then login it verify it works.
&lt;br /&gt;&lt;br /&gt;
If you are not allowing all actions and are explicitly defining the actions you are allowing, remember that for &lt;a href=&quot;/2010/11/static-pages.html&quot;&gt;static pages&lt;/a&gt; the default action is &lt;code&gt;&#39;display&#39;&lt;/code&gt; and is required for authorization to view those pages.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/4375276820576784126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2010/11/authentication.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/4375276820576784126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/4375276820576784126'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2010/11/authentication.html' title='Authentication'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-565220015249030667</id><published>2010-11-09T20:55:00.006-07:00</published><updated>2010-11-09T21:17:10.391-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="pagination"/><category scheme="http://www.blogger.com/atom/ns#" term="users"/><title type='text'>Pagination</title><content type='html'>With a short list of records, the basic view is good enough, however, once the number of records exceeds 50 or so, it is helpful to use CakePHP&#39;s built in pagination to display pages on multiple pages.

First edit &lt;code&gt;/app/controllers/users_controller.php&lt;/code&gt; and replace this line
&lt;pre&gt;$this-&gt;set(&#39;users&#39;,$this-&gt;User-&gt;find(&#39;all&#39;));&lt;/pre&gt;with this one
&lt;pre&gt;$this-&gt;set(&#39;users&#39;, $this-&gt;paginate());&lt;/pre&gt;
Save and upload the file. Now if you browse to &lt;a href=&quot;http://drug-ed.com/&quot;&gt;http://drug-ed.com/&lt;/a&gt; it still works because the data pulled from the database is the same, we just haven&#39;t taken advantage of the pagination features yet.

Edit &lt;code&gt;/app/views/users/index.ctp&lt;/code&gt; and replace
&lt;pre&gt;&amp;nbsp; &amp;nbsp; &amp;lt;th&amp;gt;ID&amp;lt;/th&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;th&amp;gt;Username&amp;lt;/th&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;th&amp;gt;First Name&amp;lt;/th&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;th&amp;gt;Last Name&amp;lt;/th&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;th&amp;gt;Email&amp;lt;/th&amp;gt;&lt;/pre&gt;with
&lt;pre&gt;&amp;nbsp; &amp;nbsp; &amp;lt;th&amp;gt;&amp;lt;?php echo $this-&amp;gt;Paginator-&amp;gt;sort(&#39;id&#39;);?&amp;gt;&amp;lt;/th&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;th&amp;gt;&amp;lt;?php echo $this-&amp;gt;Paginator-&amp;gt;sort(&#39;username&#39;);?&amp;gt;&amp;lt;/th&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;th&amp;gt;&amp;lt;?php echo $this-&amp;gt;Paginator-&amp;gt;sort(&#39;first_name&#39;);?&amp;gt;&amp;lt;/th&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;th&amp;gt;&amp;lt;?php echo $this-&amp;gt;Paginator-&amp;gt;sort(&#39;last_name&#39;);?&amp;gt;&amp;lt;/th&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;th&amp;gt;&amp;lt;?php echo $this-&amp;gt;Paginator-&amp;gt;sort(&#39;email&#39;);?&amp;gt;&amp;lt;/th&amp;gt;&lt;/pre&gt;Then after the users table within the users division add
&lt;pre&gt;&amp;nbsp; &amp;nbsp; &amp;lt;p&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;?php
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; echo $this-&amp;gt;Paginator-&amp;gt;counter(array(&#39;format&#39; =&amp;gt; __(&#39;Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%&#39;, true)));
&amp;nbsp; &amp;nbsp; ?&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;/p&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;div class=&quot;paging&quot;&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;?php echo $this-&amp;gt;Paginator-&amp;gt;prev(&#39;&amp;lt;&amp;lt; &#39; . __(&#39;previous&#39;, true), array(), null, array(&#39;class&#39;=&amp;gt;&#39;disabled&#39;));?&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;lt;?php echo $this-&amp;gt;Paginator-&amp;gt;numbers();?&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; | &amp;lt;?php echo $this-&amp;gt;Paginator-&amp;gt;next(__(&#39;next&#39;, true) . &#39; &amp;gt;&amp;gt;&#39;, array(), null, array(&#39;class&#39; =&amp;gt; &#39;disabled&#39;));?&amp;gt;
&amp;nbsp; &amp;nbsp; &amp;lt;/div&amp;gt;&lt;/pre&gt;
Save and upload the file then browse to &lt;a href=&quot;http://drug-ed.com/&quot;&gt;http://drug-ed.com/&lt;/a&gt; to verify that it works. You can now click on the headers of each column to sort the users, as well as view them on multiple pages, though it requires more than 20 records for a new page.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/565220015249030667/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2010/11/pagination.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/565220015249030667'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/565220015249030667'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2010/11/pagination.html' title='Pagination'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-1014854752811678251</id><published>2010-11-09T20:43:00.010-07:00</published><updated>2011-08-08T12:25:09.311-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="elements"/><title type='text'>Elements</title><content type='html'>Elements are HTML elements that you will use repeatedly within different views. You create the element then include it within your view code. They are stored within the &lt;code&gt;/app/views/elements/&lt;/code&gt; directory.
&lt;br /&gt;&lt;br /&gt;
Create &lt;code&gt;/app/views/elements/banner.ctp&lt;/code&gt;
&lt;pre&gt;&amp;lt;?php
echo &quot;&amp;lt;div class=\&quot;clear centerText\&quot;&amp;gt;
&amp;lt;script type=\&quot;text/javascript\&quot;&amp;gt;&amp;lt;!--
google_ad_client = \&quot;pub-9280152324836673\&quot;;
google_ad_slot = \&quot;5630351766\&quot;;
google_ad_width = 728;
google_ad_height = 90;
//--&gt;
&amp;lt;/script&amp;gt;
&amp;lt;script type=\&quot;text/javascript\&quot;
src=\&quot;http://pagead2.googlesyndication.com/pagead/show_ads.js\&quot;&amp;gt;
&amp;lt;/script&amp;gt;&amp;lt;/div&amp;gt;&quot;;
?&amp;gt;&lt;/pre&gt;
Save and upload the file then edit &lt;code&gt;/app/views/users/index.ctp&lt;/code&gt;
Add the following line at the bottom of the file:
&lt;pre&gt;&amp;lt;?php echo $this-&gt;element(&#39;banner&#39;); ?&amp;gt;&lt;/pre&gt;
Save and upload the file then browse to &lt;a href=&quot;http://drug-ed.com/&quot;&gt;http://drug-ed.com/&lt;/a&gt; to verify it works. Since the element only exists on the &lt;code&gt;/app/views/users/index.ctp&lt;/code&gt; page, it will only appear on that page. If you include the element on the &lt;code&gt;/app/views/layouts/default.ctp&lt;/code&gt; page, it will display on every page.
&lt;br /&gt;&lt;br /&gt;
Remove that line from the bottom of &lt;code&gt;/app/views/users/index.ctp&lt;/code&gt; and add it to the &quot;footer&quot; div of the &lt;code&gt;/app/views/layouts/default.ctp&lt;/code&gt; page.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/1014854752811678251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2010/11/elements.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/1014854752811678251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/1014854752811678251'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2010/11/elements.html' title='Elements'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-4010553174840275076</id><published>2010-11-09T20:02:00.009-07:00</published><updated>2011-08-08T12:25:50.452-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="pages"/><title type='text'>Static Pages</title><content type='html'>Not all pages in your site will be dynamic. Some pages, such as an &quot;About&quot; page, will be static and CakePHP has a Pages controller for just that purpose. The pages controller is located by default in &lt;code&gt;/cake/libs/controllers/pages_controller.php&lt;/code&gt; If you need to edit it for any reason, copy the file to &lt;code&gt;/app/controllers/&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;
Static pages are stored in &lt;code&gt;/app/views/pages/&lt;/code&gt; and displayed using the display action. By default they are addressed using site root/pages/page name.
&lt;br /&gt;&lt;br /&gt;
Create any static pages with the &lt;code&gt;.ctp&lt;/code&gt; extension and include any html formatting you want in your page.
&lt;br /&gt;&lt;br /&gt;
Create &lt;code&gt;/app/views/pages/about.ctp&lt;/code&gt;
&lt;pre&gt;&amp;lt;?php $this-&gt;set(&quot;title_for_layout&quot;, &#39;About Drug-ed.com&#39;); ?&amp;gt;
&amp;lt;h2&amp;gt;About Drug-Ed.com&amp;lt;/h2&amp;gt;
&amp;lt;p&amp;gt;Drug-Ed.com is a free drug education and medication reminder service for your daily medication needs. Set up your drug schedule online and have reminders emailed to you or texted to your mobile phone daily. We want to make taking your medication as easy and hassle free as possible.&amp;lt;/p&amp;gt;&lt;/pre&gt;
Remember when I said we should change the &lt;a href=&quot;/2010/11/page-title.html&quot;&gt;page title&lt;/a&gt; in the controller? Well with static pages it is easier to just set them in the page itself.
&lt;br /&gt;&lt;br /&gt;
Save and upload the file then browse to &lt;a href=&quot;http://drug-ed.com/pages/about&quot;&gt;http://drug-ed.com/pages/about&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
When using the &lt;a href=&quot;/2010/11/layout-default.html&quot;&gt;HTML helper&lt;/a&gt; to create links to static pages remember that &lt;code&gt;pages&lt;/code&gt; is the controller and &lt;code&gt;display&lt;/code&gt; is the action so they either must be explicitly declared, or create a hard link instead.
&lt;pre&gt;&amp;lt;?php echo $this-&amp;gt;Html-&amp;gt;link(&#39;Downloads&#39;, array(&#39;controller&#39; =&amp;gt; &#39;pages&#39;, &#39;action&#39;=&amp;gt;&#39;display&#39;, &#39;downloads&#39;)); ?&amp;gt;
&amp;lt;?php echo $this-&amp;gt;Html-&amp;gt;link(&#39;Downloads&#39;, &#39;/pages/downloads&#39;); ?&amp;gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/4010553174840275076/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2010/11/static-pages.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/4010553174840275076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/4010553174840275076'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2010/11/static-pages.html' title='Static Pages'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-1501607070997899381</id><published>2010-11-09T18:56:00.006-07:00</published><updated>2011-08-08T12:26:12.435-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="helpers"/><category scheme="http://www.blogger.com/atom/ns#" term="layout"/><title type='text'>Layout: Default</title><content type='html'>Further changes to the default layout that we created &lt;a href=&quot;/2010/11/page-title.html&quot;&gt;previously&lt;/a&gt; will affect all page views, so develop your default layout with that in mind, putting elements on the page that you would like to be on every page of your site, such as a site logo, main navigation, and copyright notice.
&lt;br /&gt;&lt;br /&gt;
First though, a word about images. Static image files for the site should go into the directory &lt;code&gt;/app/webroot/img/&lt;/code&gt; as this directory allows direct access to the images without processing through a controller and when using the HTML helper (see below) you don&#39;t have to remember the beginning path to the image.
&lt;br /&gt;&lt;br /&gt;
The site &quot;favicon.ico&quot; file should go in the &lt;code&gt;/app/webroot/&lt;/code&gt; directory. There is a default file already there, so when you have an image for your site simply replace it.
&lt;br /&gt;&lt;br /&gt;
Edit &lt;code&gt;/app/views/layouts/default.ctp&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;
Inside the &quot;header&quot; div at the top remove the line beginning with &quot;&amp;lt;h1&amp;gt;&quot; and add the following:
&lt;pre&gt;&amp;nbsp; &amp;nbsp; &amp;lt;div class=&quot;logo&quot;&amp;gt;&amp;lt;?php echo $this-&amp;gt;Html-&amp;gt;link($this-&amp;gt;Html-&amp;gt;image(&#39;drug-ed-logo.png&#39;, array(&quot;alt&quot; =&amp;gt; &quot;Drug-Ed.com&quot;)), Router::url(&#39;/&#39;), array(&#39;escape&#39; =&amp;gt; false)); ?&amp;gt;&amp;lt;/div&amp;gt;&lt;/pre&gt;
The Html Helper is included in CakePHP to make creating links and other Html elements easier to code dynamically. The default format for using a helper is with &lt;code&gt;$this-&gt;HelperName&lt;/code&gt;. Observe in the above code that an image element is contained within an link element. Since the image is stored within the &lt;code&gt;/app/webroot/img/&lt;/code&gt; directory as mentioned above, the path to the image is not required since the helper automatically includes it.
&lt;br /&gt;&lt;br /&gt;
If your Html helper link includes html entities, such as the above image, by default the code is escaped out. To turn that feature off and allow the html in the title to be displayed properly add the &lt;code&gt;options&lt;/code&gt; array to the &lt;code&gt;link&lt;/code&gt; function as above.
&lt;br /&gt;&lt;br /&gt;
Save and upload the file then browse to site root to observe the changes.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/1501607070997899381/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2010/11/layout-default.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/1501607070997899381'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/1501607070997899381'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2010/11/layout-default.html' title='Layout: Default'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-6628502892296575279</id><published>2010-11-09T18:16:00.008-07:00</published><updated>2011-08-08T12:26:20.237-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="controller"/><category scheme="http://www.blogger.com/atom/ns#" term="layout"/><category scheme="http://www.blogger.com/atom/ns#" term="page title"/><category scheme="http://www.blogger.com/atom/ns#" term="users"/><title type='text'>Page Title</title><content type='html'>From your home page observe the page title, it should be something like this:
&quot;CakePHP: the rapid development php framework: Users&quot;
&lt;br /&gt;&lt;br /&gt;
The first part of the title is defined in the default layout. The layout predefines the wrapper HTML code of every page. This file is located in &lt;code&gt;/cake/libs/view/layouts/default.ctp&lt;/code&gt; and before editing it you should move it to &lt;code&gt;/app/views/layouts/default.ctp&lt;/code&gt;
&lt;br /&gt;&lt;br /&gt;
Next, edit the page and remove the following line:
&lt;pre&gt;&amp;lt;?php __(&#39;CakePHP: the rapid development php framework:&#39;); ?&amp;gt;&lt;/pre&gt;
Upload the file and test it and your home page title should just read &quot;Users&quot;.
&lt;br /&gt;&lt;br /&gt;
Now click on the username and the title will read &quot;Scaffold :: View :: Users&quot;
While the default titles can be helpful, you will want to change them to reflect your site&#39;s method.
&lt;br /&gt;&lt;br /&gt;
Edit &lt;code&gt;/app/controllers/users_controller.php&lt;/code&gt; and for the first line in the &lt;code&gt;index()&lt;/code&gt; method add the following:
&lt;pre&gt;$this-&gt;set(&quot;title_for_layout&quot;, &#39;Drug-ed.com : Drug Education and Medication Adherence&#39;);&lt;/pre&gt;
Save the changes upload the file and test it at site root. This command will also work if you add it to &lt;code&gt;/app/views/users/index.ctp&lt;/code&gt;, however, since you are modifying variables it is best practice to do it within the controller.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/6628502892296575279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2010/11/page-title.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/6628502892296575279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/6628502892296575279'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2010/11/page-title.html' title='Page Title'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-9125544055182990224</id><published>2010-11-09T17:57:00.005-07:00</published><updated>2011-08-08T12:26:26.100-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="routing"/><title type='text'>Routing</title><content type='html'>By default, requests to your site root are routed by CakePHP to a home view, &lt;code&gt;/apps/views/pages/home.ctp&lt;/code&gt;. By changing the routing, you can direct the request to any controller and action you choose.
&lt;br /&gt;&lt;br /&gt;
Edit &lt;code&gt;/app/config/routes.php&lt;/code&gt;
Comment out &lt;pre&gt;&amp;nbsp; &amp;nbsp; Router::connect(&#39;/&#39;, array(&#39;controller&#39; =&amp;gt; &#39;pages&#39;, &#39;action&#39; =&amp;gt; &#39;display&#39;, &#39;home&#39;));&lt;/pre&gt;Then add
&lt;pre&gt;&amp;nbsp; &amp;nbsp; Router::connect(&#39;/&#39;, array(&#39;controller&#39;=&amp;gt;&#39;users&#39;, &#39;action&#39;=&amp;gt;&#39;index&#39;));&lt;/pre&gt;
Now browse to &lt;a href=&quot;http://drug-ed.com/&quot;&gt;http://drug-ed.com/&lt;/a&gt; and verify it goes to the users index.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/9125544055182990224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2010/11/routing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/9125544055182990224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/9125544055182990224'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2010/11/routing.html' title='Routing'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7015944332496215751.post-7477331349400052839</id><published>2010-11-04T18:31:00.011-07:00</published><updated>2012-03-12T14:17:40.634-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="model"/><category scheme="http://www.blogger.com/atom/ns#" term="users"/><category scheme="http://www.blogger.com/atom/ns#" term="validation"/><title type='text'>Validate Model: User</title><content type='html'>Rule 1: Never trust user input&lt;br /&gt;
Rule 2: When in doubt, see rule 1
&lt;br /&gt;&lt;br /&gt;
For every model you should create a &lt;code&gt;validate&lt;/code&gt; variable which will be used to validate input fields. For our &lt;code&gt;user&lt;/code&gt; model we need to verify that username and email are unique on creation.
&lt;br /&gt;&lt;br /&gt;
Since validation can be quite complex, building the validation variable one field at a time can be helpful. For full details on data validation see &lt;a href=&quot;http://book.cakephp.org/view/1143/Data-Validation&quot;&gt;http://book.cakephp.org/view/1143/Data-Validation&lt;/a&gt;
&lt;br /&gt;&lt;br /&gt;
Edit &lt;code&gt;/app/models/user.php&lt;/code&gt; and add
&lt;pre&gt;&amp;nbsp; &amp;nbsp; var $validate = array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;username&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;alphanumeric&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;rule&#39; =&gt; &#39;/^[a-z0-9]{3,}$/i&#39;,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;required&#39; =&gt; true,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;message&#39; =&gt; &#39;Username must contain only letters and numbers.&#39;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;unique&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;rule&#39; =&gt; &#39;isUnique&#39;,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;message&#39; =&gt; &#39;This username is already taken.&#39;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;minlength&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;rule&#39; =&gt; array(&#39;minlength&#39;, 5),
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;message&#39; =&gt; &#39;Username must be at least 5 characters.&#39;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ) 
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )
&amp;nbsp; &amp;nbsp; );&lt;/pre&gt;
Upload the file then browse to &lt;a href=&quot;http://drug-ed.com/users/add&quot;&gt;http://drug-ed.com/users/add&lt;/a&gt; and observe how the &quot;Username&quot; field label is bolded and followed by a red asterisk helping to identify the required aspect of that field. Test your validation rule by trying a 2 letter username, or one composed of special characters.
&lt;br /&gt;&lt;br /&gt;
Now that you are sure that field validation is working properly, add the next field.
Edit &lt;code&gt;/app/models/user.php&lt;/code&gt; and add at the end of the &lt;code&gt;validate&lt;/code&gt; array
&lt;pre&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;email&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;email&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;rule&#39; =&gt; &#39;email&#39;,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;required&#39; =&gt; true,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;message&#39; =&gt; &#39;You must enter a valid email address.&#39;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;unique&#39; =&gt; array(
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;rule&#39; =&gt; &#39;isUnique&#39;,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;on&#39; =&gt; &#39;create&#39;,
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;message&#39; =&gt; &#39;This email address is already on record.&#39;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )
&amp;nbsp; &amp;nbsp; );&lt;/pre&gt;Notice the line &lt;code&gt;&#39;on&#39; =&gt; &#39;create&#39;&lt;/code&gt; in the email validation. When editing a user the &lt;code&gt;isUnique&lt;/code&gt; rule will fail because the user&#39;s email is already in the database! Changing it to only verify when you create an new user will prevent this problem.
&lt;br /&gt;&lt;br /&gt;
Upload the file then browse to &lt;a href=&quot;http://drug-ed.com/users/add&quot;&gt;http://drug-ed.com/users/add&lt;/a&gt; to again verify it works as intended.</content><link rel='replies' type='application/atom+xml' href='http://drug-ed.blogspot.com/feeds/7477331349400052839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://drug-ed.blogspot.com/2010/11/validate-model-user.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/7477331349400052839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7015944332496215751/posts/default/7477331349400052839'/><link rel='alternate' type='text/html' href='http://drug-ed.blogspot.com/2010/11/validate-model-user.html' title='Validate Model: User'/><author><name>Charles Patterson</name><uri>http://www.blogger.com/profile/16229134789904572271</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='27' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfu7Lw3afnglcbV9oC08zAByjCeLYEXxqE9PC2RDB8EAfBxmcpfdDBBnDzNQeqiwIJgnfzTLZjJ7ih9WhYr5gfua7meVnVMS3Ga6WCDAvboV7BZNZixnnt0TI12ZgsYQ/s1600-r/gargoyle.gif'/></author><thr:total>0</thr:total></entry></feed>