<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jonah's Thoughts &#187; scenarios</title>
	<atom:link href="http://php-thoughts.cubedwater.com/tag/scenarios/feed/" rel="self" type="application/rss+xml" />
	<link>http://php-thoughts.cubedwater.com</link>
	<description>On PHP and things related</description>
	<lastBuildDate>Mon, 21 Jun 2010 01:38:44 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Safe attributes tip</title>
		<link>http://php-thoughts.cubedwater.com/2009/safe-attributes-tip/</link>
		<comments>http://php-thoughts.cubedwater.com/2009/safe-attributes-tip/#comments</comments>
		<pubDate>Fri, 20 Feb 2009 00:35:12 +0000</pubDate>
		<dc:creator>Jonah</dc:creator>
				<category><![CDATA[Enhancement]]></category>
		<category><![CDATA[Yii]]></category>
		<category><![CDATA[scenarios]]></category>

		<guid isPermaLink="false">http://php-thoughts.cubedwater.com/?p=163</guid>
		<description><![CDATA[<link rel="stylesheet" type="text/css" href="/wp-content/plugins/syntax.css" />In my last two posts [1, 2] I explained how to define scenario-based validation rules and safe attributes.  Something I have noted is that whenever I end up specifying an attribute as &#8220;required&#8221; in the validation rules(), I also always end up specifying it as &#8220;safe&#8221; in safeAttributes() under the same scenario.  This [...]]]></description>
			<content:encoded><![CDATA[<link rel="stylesheet" type="text/css" href="/wp-content/plugins/syntax.css" /><p>In my last two posts [<a href="http://php-thoughts.cubedwater.com/2009/validation-scenarios/">1</a>, <a href="http://php-thoughts.cubedwater.com/2009/safe-attribute-scenarios/">2</a>] I explained how to define scenario-based validation rules and safe attributes.  Something I have noted is that whenever I end up specifying an attribute as &#8220;required&#8221; in the validation rules(), I also always end up specifying it as &#8220;safe&#8221; in safeAttributes() under the same scenario.  This got me thinking &#8211; is it possible that every &#8220;required&#8221; attribute must also be &#8220;safe&#8221; on a given scenario?  The answer to that seems to be yes.  So I thought, why be redundant?  So I went about the task of teaching Yii that all &#8220;required&#8221; attributes are also &#8220;safe&#8221;.  It seems the most elegant way to do this is by extending getSafeAttributeNames() in your model. So that&#8217;s what I did.  Now, I&#8217;ll share with you.  Just drop this code in any model that you would like to have this behavior.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span class="kw2">&lt;?php</span>
<span class="coMULTI">/*
* I extended this method so that yii will &quot;automagically&quot; understand that
* 'required' attributes (in the given scenario) are also 'safe'.  This way,
* when defining 'safe' attributes in the safeAttributes() method, you can
* neglect to define attributes as safe that you have already defined at &quot;required&quot;
* in your rules() method.  This basically saves typing (and in some cases stupid
* mistakes), which I am always a fan of.  This method could be moved to another model
* from which other models like this could inherit from if you wish.
* 
* You should NOT call this method directly but it is used by Yii internally
*/</span>
<span class="kw2">public</span> <span class="kw2">function</span> getSafeAttributeNames<span class="br0">&#40;</span><span class="re0">$scenario</span><span class="sy0">=</span><span class="st_h">''</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
	<span class="re0">$safe</span> <span class="sy0">=</span> parent<span class="sy0">::</span><span class="me2">getSafeAttributeNames</span><span class="br0">&#40;</span><span class="re0">$scenario</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
	<span class="kw1">foreach</span> <span class="br0">&#40;</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">validators</span> <span class="kw1">as</span> <span class="re0">$validator</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
		<span class="kw1">if</span> <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="kw3">get_class</span><span class="br0">&#40;</span><span class="re0">$validator</span><span class="br0">&#41;</span> <span class="sy0">!=</span> <span class="st_h">'CRequiredValidator'</span><span class="br0">&#41;</span> <span class="sy0">||</span> <span class="sy0">!</span><span class="re0">$validator</span><span class="sy0">-&gt;</span><span class="me1">applyTo</span><span class="br0">&#40;</span><span class="re0">$scenario</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">continue</span><span class="sy0">;</span>
		<span class="re0">$safe</span> <span class="sy0">=</span> <span class="kw3">array_merge</span><span class="br0">&#40;</span><span class="re0">$safe</span><span class="sy0">,</span> <span class="re0">$validator</span><span class="sy0">-&gt;</span><span class="me1">attributes</span><span class="br0">&#41;</span><span class="sy0">;</span>
	<span class="br0">&#125;</span>
	<span class="kw1">return</span> <span class="kw3">array_unique</span><span class="br0">&#40;</span><span class="re0">$safe</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>Enjoy if you wish and give feedback.</p>
<p>One thing to worry about is speed however.  Every time this method is called, it loops through all the validators.  If you have a <em>lot</em> of validation rules this could be unwanted.  On the other hand, yii only checks the safe attributes on CModel::setAttributes(), which is generally only called on requests with submitted POST data (e.g. forms, and users don&#8217;t often expect those pages to be lightning fast).  Anyways, I&#8217;m making this code snipped sound slower than it actually is.  It might be interesting to check how many times this method is called on a given request.</p>
]]></content:encoded>
			<wfw:commentRss>http://php-thoughts.cubedwater.com/2009/safe-attributes-tip/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Safe attribute scenarios</title>
		<link>http://php-thoughts.cubedwater.com/2009/safe-attribute-scenarios/</link>
		<comments>http://php-thoughts.cubedwater.com/2009/safe-attribute-scenarios/#comments</comments>
		<pubDate>Tue, 17 Feb 2009 22:44:59 +0000</pubDate>
		<dc:creator>Jonah</dc:creator>
				<category><![CDATA[Yii]]></category>
		<category><![CDATA[scenarios]]></category>

		<guid isPermaLink="false">http://php-thoughts.cubedwater.com/?p=162</guid>
		<description><![CDATA[<link rel="stylesheet" type="text/css" href="/wp-content/plugins/syntax.css" /><link rel="stylesheet" type="text/css" href="/wp-content/plugins/syntax.css" /><link rel="stylesheet" type="text/css" href="/wp-content/plugins/syntax.css" />If you read my last article on validation scenarios then you may understand why in different scenarios you may need different attributes to be required.  However you may have noticed a missing link &#8211; what if in different scenarios you also need different attributes to be considered as &#8220;safe&#8221;?
If you have no idea about [...]]]></description>
			<content:encoded><![CDATA[<link rel="stylesheet" type="text/css" href="/wp-content/plugins/syntax.css" /><link rel="stylesheet" type="text/css" href="/wp-content/plugins/syntax.css" /><link rel="stylesheet" type="text/css" href="/wp-content/plugins/syntax.css" /><p>If you read <a href="http://php-thoughts.cubedwater.com/2009/validation-scenarios/">my last article on validation scenarios</a> then you may understand why in different scenarios you may need different attributes to be required.  However you may have noticed a missing link &#8211; what if in different scenarios you also need different attributes to be considered as &#8220;safe&#8221;?</p>
<p>If you have no idea about what I am taking about then you probably don&#8217;t know that in your model you can specify which attributes are &#8220;safe&#8221; to massively assign to a model via CModel::setAttributes().</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span class="kw2">&lt;?php</span>
<span class="kw2">public</span> <span class="kw2">function</span> safeAttributes<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
	<span class="kw1">return</span> <span class="kw3">array</span><span class="br0">&#40;</span>
		<span class="co1">//these attributes are safe to massively assign</span>
		<span class="st_h">'attribute1, attribute2'</span><span class="sy0">,</span>
	<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="sy1">?&gt;</span></pre></div></div>

<p>By default, all columns in the table are considered safe except the primary key column (attributes defined in the model are <em>not</em> considered safe by default)</p>
<p>The reason you might not want all attributes to be safe is if for instance you have fields which determine things such as access level.  For instance what if you had a User model with a `is_admin` field.  If you let `is_admin` be defined as safe, you have a security hole, as someone can take a tool such as <a href="https://addons.mozilla.org/en-US/firefox/addon/1290">urlparams</a> and easily set himself as an admin.</p>
<p>Now you may actually want &#8220;is_admin&#8221; to be defined as safe in <em>certain scenarios</em>, such as an user administrative page.  Thus, as of Yii 1.0.2, you can define scenarios through safeAttributes() which was the initial reason for writing this article.</p>
<p>I will simply use a code example taken from the <a href="http://www.yiiframework.com/doc/api/CModel#safeAttributes">Yii Class Reference</a> this time.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span class="kw2">&lt;?php</span>
<span class="kw2">public</span> <span class="kw2">function</span> safeAttributes<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
	<span class="kw1">return</span> <span class="kw3">array</span><span class="br0">&#40;</span>
	   <span class="co1">// these attributes can be massively assigned in any scenario</span>
	   <span class="co1">// that is not explicitly specified below</span>
	   <span class="st_h">'attr1, attr2, ...'</span><span class="sy0">,</span>
&nbsp;
	   <span class="co1">// these attributes can be massively assigned only in scenario 1</span>
	   <span class="st_h">'scenario1'</span> <span class="sy0">=&gt;</span> <span class="st_h">'attr2, attr3, ...'</span><span class="sy0">,</span> <span class="co1">//Eg in this scenario attr1 is NOT safe</span>
&nbsp;
	   <span class="co1">// these attributes can be massively assigned only in scenario 2</span>
	   <span class="st_h">'scenario2'</span> <span class="sy0">=&gt;</span> <span class="st_h">'attr1, attr3, ...'</span><span class="sy0">,</span>
	<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>Now you may set the scenario to use via CModel::setAttributes()</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span class="kw2">&lt;?php</span>
<span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">setAttributes</span><span class="br0">&#40;</span><span class="kw3">array</span> <span class="sy0">&lt;</span>data<span class="sy0">&gt;,</span> string <span class="sy0">&lt;</span>scenario name<span class="sy0">&gt;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">//Example:</span>
<span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">setAttributes</span><span class="br0">&#40;</span><span class="re0">$_POST</span><span class="br0">&#91;</span><span class="st_h">'User'</span><span class="br0">&#93;</span><span class="sy0">,</span> <span class="st_h">'update'</span><span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://php-thoughts.cubedwater.com/2009/safe-attribute-scenarios/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Validation scenarios</title>
		<link>http://php-thoughts.cubedwater.com/2009/validation-scenarios/</link>
		<comments>http://php-thoughts.cubedwater.com/2009/validation-scenarios/#comments</comments>
		<pubDate>Mon, 16 Feb 2009 22:00:13 +0000</pubDate>
		<dc:creator>Jonah</dc:creator>
				<category><![CDATA[Yii]]></category>
		<category><![CDATA[scenarios]]></category>

		<guid isPermaLink="false">http://php-thoughts.cubedwater.com/?p=106</guid>
		<description><![CDATA[<link rel="stylesheet" type="text/css" href="/wp-content/plugins/syntax.css" /><link rel="stylesheet" type="text/css" href="/wp-content/plugins/syntax.css" />As of Yii 1.0.2 you may now define validation scenarios.  This is very useful if for instance you have multiple places in your application that you validate a model, but in each instance you may want different validation rules.  For instance, perhaps in your user registration form you want to have the &#8220;username&#8221;, [...]]]></description>
			<content:encoded><![CDATA[<link rel="stylesheet" type="text/css" href="/wp-content/plugins/syntax.css" /><link rel="stylesheet" type="text/css" href="/wp-content/plugins/syntax.css" /><p>As of Yii 1.0.2 you may now define validation scenarios.  This is very useful if for instance you have multiple places in your application that you validate a model, but in each instance you may want different validation rules.  For instance, perhaps in your user registration form you want to have the &#8220;username&#8221;, &#8220;email&#8221; and &#8220;password&#8221; fields to be required, while on your &#8220;user recovery&#8221; page, you only want the &#8220;email&#8221; field to be required.  You may see a problem here.  If you set all the fields to be required, then your user recovery page won&#8217;t work, as it does not allow a user to supply neither a password nor a username.</p>
<p>The perfect solution to this are validation scenarios.  You can attach a validation scenario to a validation rule through the &#8216;on&#8217; property.  You may already know you can set the &#8216;on&#8217; property to either &#8216;insert&#8217; or &#8216;update&#8217;, which will automatically cause the rule to only be used on the corresponding type of save.  However sometimes these two options are not enough.  So now with this new enhancement, you may set it to any value you want.  Let me show an example:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span class="kw2">&lt;?php</span>
<span class="co1">//in user model</span>
<span class="kw2">public</span> <span class="kw2">function</span> rules<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
	<span class="kw1">return</span> <span class="kw3">array</span><span class="br0">&#40;</span>
		<span class="co1">//Set required fields</span>
 		<span class="co1">//Applies to 'register' scenario</span>
 		<span class="co1">//Note 'on' property</span>
		<span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'username, password, password_repeat, email'</span><span class="sy0">,</span> <span class="st_h">'required'</span><span class="sy0">,</span> <span class="st_h">'on'</span> <span class="sy0">=&gt;</span> <span class="st_h">'register'</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp;
		<span class="co1">//Applies to 'recover' scenario</span>
		<span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'email'</span><span class="sy0">,</span> <span class="st_h">'required'</span><span class="sy0">,</span> <span class="st_h">'on'</span> <span class="sy0">=&gt;</span> <span class="st_h">'recover'</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp;
		<span class="co1">//Applies to all scenarios</span>
		<span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'username, password'</span><span class="sy0">,</span> <span class="st_h">'length'</span><span class="sy0">,</span> <span class="st_h">'max'</span><span class="sy0">=&gt;</span><span class="nu0">35</span><span class="sy0">,</span> <span class="st_h">'min'</span><span class="sy0">=&gt;</span><span class="nu0">3</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp;
		<span class="co1">//This rule checks if the username is unique in the database in</span>
		<span class="co1">//the 'register' scenario (we don't want it to check for uniqueness</span>
		<span class="co1">//on the login page for instance)</span>
		<span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'username'</span><span class="sy0">,</span> <span class="st_h">'unique'</span><span class="sy0">,</span> <span class="st_h">'on'</span> <span class="sy0">=&gt;</span> <span class="st_h">'register'</span><span class="br0">&#41;</span><span class="sy0">,</span>
&nbsp;
		<span class="co1">//This rule applies to 'register' and 'update' scenarios</span>
		<span class="co1">//Compares 'password' field to 'password_repeat' to make sure they are the same</span>
		<span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'password'</span><span class="sy0">,</span> <span class="st_h">'compare'</span><span class="sy0">,</span> <span class="st_h">'on'</span> <span class="sy0">=&gt;</span> <span class="st_h">'register, update'</span><span class="br0">&#41;</span><span class="sy0">,</span>
	<span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>With this setup Yii will be able to tell which fields are required in which scenarios.  As a bonus I threw some other rules for example.  Reading the comments will give you an understanding of that.  You may also note from the &#8216;compare&#8217; rule that you may define a rule to be used on multiple scenarios by separating them with commas.</p>
<p>Now when you wish to run validation under a specific scenario you must define it in when calling CModel::validate(), as so</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span class="kw2">&lt;?php</span>
<span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">validate</span><span class="br0">&#40;</span><span class="st_h">'&lt;scenarioName&gt;'</span><span class="br0">&#41;</span><span class="sy0">;</span> <span class="co1">//runs validation under the given scenario</span>
&nbsp;
<span class="co1">//example:</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">validate</span><span class="br0">&#40;</span><span class="st_h">'register'</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
	<span class="re0">$user</span><span class="sy0">-&gt;</span><span class="me1">save</span><span class="br0">&#40;</span><span class="kw2">false</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>So the above example will validate the user under the &#8216;register&#8217; scenario.</p>
<p>Leave a comment if I have left any unanswered questions on this enhancement</p>
]]></content:encoded>
			<wfw:commentRss>http://php-thoughts.cubedwater.com/2009/validation-scenarios/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
	</channel>
</rss>
