Yii nested URL parameters - yii

Can anyone point me in the right direction in order to write a URL rule in order to achieve the following:
Using the base controller I want to get to each of the parameters in this url:
DomainName/clientID/fileID

Haven't tested it, but this should work:
'rules' => array(
'<clientID:\d+>/<fileID:\d+>' => 'myBaseController/myAction',
)
Just make sure the one rule gets added before your Yii default URL rules. FYI, the rule assumes that both client ID and file ID are integers. If fileID contains letters, change it to fileID:\w+.

$url = $this->createUrl('timeSheetDetaile/create',array('timesheetID'=>$timeSheedID,'dayID'=>1));
first param is the name of your controller and second array is $_GET params ..
have fun.

Related

How to pass a parameter to a scenario in Yii?

How to pass $id to search scenario? Maybe in model look like this, so I can call like in controller like:
$model = new job('search',$id);
I think that you are trying to do a search. Search is one thing, a "scenario" is something else.
Scenarios are used in validation rules in order to be able to validate the same model in multiple ways depending from where you're inserting/adding OR searching data.
There's also a scenario called 'search' that is used by the model's search() method, but I tell you why:
There are a couple of ways to search for something in your database using Yii, I will mention two:
1) By using ClassName::model()->findCommandHere
And there are a couple of them:
ClassName::model()->findByPk($id);
ClassName::model()->findAll("id=$id");
ClassName::model()->findByAttributes(array('id'=>$id));
And so on, more here: http://www.yiiframework.com/doc/guide/1.1/en/database.ar#reading-record
2) By using the model's search() method
This way of finding data is mostly used for easily creating search pages and in combination with data grids.
If you generate CRUD code with the GII code generation tool it will generate all the parts for you, but I will explain each part how it works.
This code is from the blog demo found in Yii files:
In controller it defines a $model using Post class and 'search' as scenario.
$model=new Post('search');
if(isset($_GET['Post'])) // <- checks if there are search params in the URL
$model->attributes=$_GET['Post']; // <- assigns all search params masively to the model (later you'll see why)
$this->render('admin',array(
'model'=>$model,
));
The 'search' scenario here tells Yii what validation rules to use when assigning search parameters directly from $_GET (URL).
You can see that the params are assigned massively to reduce code written but $model->attributes=$_GET['Post'] it is the same as doing:
$model->title=$_GET['Post']['title'];
$model->status=$_GET['Post']['status'];
In the Post model you can find the validation rules for the search scenario. Tells Yii that it is safe to assign title and status fields in order to later use them in the search.
public function rules()
{
return array(
// ... //
array('title, status', 'safe', 'on'=>'search'),
);
}
Then also in the Post model you can see the search() method that will actually be used to get the data:
public function search()
{
$criteria=new CDbCriteria;
$criteria->compare('title',$this->title,true);
$criteria->compare('status',$this->status);
return new CActiveDataProvider('Post', array(
'criteria'=>$criteria,
'sort'=>array(
'defaultOrder'=>'status, update_time DESC',
),
));
}
The search method creates a "criteria" and applies the desired way of filtering using the values you have previously assigned to this model. See the $this->title it comes from the $model->attributes=$_GET['Post'] you used in the controller.
The criteria can be used directly on the model, such as Post::model()->findAll($criteria), but in this case the search() method uses something different, a "data provider".
The data provider is a good thing because it provides you a lot of tools in one place, it returns you the data, but also the pagination, and the sorting, so you don't have to manually define more code for that purposes (CPagination, CSort).
Finally, in the view admin.php in this case it will display the results using a grid view:
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
array(
'name'=>'title',
'type'=>'raw',
'value'=>'CHtml::link(CHtml::encode($data->title), $data->url)'
),
array(
'name'=>'status',
'value'=>'Lookup::item("PostStatus",$data->status)',
'filter'=>Lookup::items('PostStatus'),
),
),
));
Now you can see that in the configuration of the grid it passes $model->search() method as the dataProvider that the grid should use.
Now the grid can access the rest of the dataProvider elements such as sort, pagination and display them on the page.
If you did not want to use the CGridView because it's a very basic table and you want to create your own html markup, you can also retrieve the dataProvider and its components one by one and place them in your HTML code and display data as you want:
$dataProvider=$model->search(); // get the dataprovider from search method
$models=$dataProvider->getData(); // actually get the data (rows) and assign them to a $models variable that you can put in a foreach loop
// show pagination somewhere
$this->widget('CLinkPager', array(
'pages' => $dataProvider->pagination,
));
// create sort links
echo $dataProvider->sort->link('title', 'Title');
So I hope it solves some of your doubts on how to use Yii for displaying/searching data.
I suggest you read the official manual: http://www.yiiframework.com/doc/guide/1.1/en/index
I also suggest to look at the API and so search there all the Yii components to see what methods and params they have: http://www.yiiframework.com/doc/api/
Also exploring the framework codebase manually is quite a good way to learn. If you don't know how CActiveDataProvider works, then find the CActiveDataProvider class file in the code and you'll see all the methods and properties that it uses, so do this for everything you don't understand how it works.
Also for beginners I recommend using a good IDE that auto-completes code and allows you to Ctrl+Click a class name and it will locate the original file where it was defined. I use NetBeans for PHP and after creating a project I add Yii framework files to the project's include paths that way NetBeans knows how to find the framework files for auto-complete and for ctrl+click.
Yes you can define scenario with parameter but that is included within the class constructor of the model
$model = new Job('search'); // creating a model with scenario search
If you wish to include more parameters, then you need to use createComponent -remember, all is a component
$model = Yii::createComponent(array('class'=>'Job','scenario'=>'search'));
I think this will simply do the job without needing any scenario
$model = new job;
$model->search($id);
But If I have failed to understand your problem then you can also try this
$model = new job('search');
$model->search($id);
Think of scenarios as a special variable that you can use in the model.
$userModel = new User("register");
$userModel->setId = 10;
which is the same
$userModel = new User();
$userModel->scenario = 10
$userModel->setId = 10;
And in your model
class Manufacturer extends CActiveRecord
{
// :
if ($this->scenario == 'register') ...
// :
}

Yii session have prefix

I am maintaining a Yii application, when i am printing Yii session it looks like this:
Array
(
[cb35f057aa124d26e8793014875ce939_id] => 1
[cb35f057aa124d26e8793014875ce939_name] => admin
[cb35f057aa124d26e8793014875ce939__states] => Array()
[cb35f057aa124d26e8793014875ce939email] => webmaster#example.com
[cb35f057aa124d26e8793014875ce939username] => admin
[cb35f057aa124d26e8793014875ce939create_at] => 2013-01-14 07:44:22
[cb35f057aa124d26e8793014875ce939lastvisit_at] => 2013-09-13 06:09:17
[cb35f057aa124d26e8793014875ce939state_id] => 1
)
i don't know where to find this number cb35f057aa124d26e8793014875ce939 so that i can use session data in my method. it is looks like fixed. does anybody know what is it ?
You should use session variables via Yii API which is
Yii::app()->session['var'] = 'something'; //setting a value
echo Yii::app()->session['var']; //reading a value
this is not session ID, this is application specific prefix which can be found by getStateKeyPrefix()
The above numbers are probably set by calling setStateKeyPrefix() function somewhere in the code.
Here is explanation of the function:
setStateKeyPrefix() - Sets a prefix for the name of the session variables storing user session data.
Additionally, you can use getStateKeyPrefix() function to see weather or not prefix is set.
The prefix is the php session id and u can get it by
Yii::app()->session->getSessionID();

Insert data from DB to URL manager

I want URL manager to process URL with the company name with my CompanyController. To do so dynamically I should get company names from my database.
Now I have such rule (but it's not dynamic):
'<alias:(vector|karnasch|tecnomagnete|ruko|bds-maschinen|exact)>' => 'company/view',
(vector|karnasch|tecnomagnete|ruko|bds-maschinen|exact) --> data to this line I want to get from database.
I can get this data (manually establish connection to db), but maybe it's another more beautiful solution with help of Yii functional. Thanks!
You can always create your custom UrlRuleclass. If you only want to parse incoming URLs you can simply return false from the createUrl() method. In the parseUrl() method you query the DB for your company names and inspect if the current URL matches. If not, you simply return false again.
Well, you don't need to do this, you just have to define the right pattern, e.g. :
'contact' => 'contact/form',
// other rules should be set before this one
'<alias:[-\w]+>' => 'company/view',
http://www.yiiframework.com/doc/guide/1.1/en/topics.url#using-named-parameters

Yii - one controller multiple urls

I'm trying to create two Yii models that are very similar and can share the same database table. One is a 'question' and one is an 'article'. They both share a title, body, and author. 'Question' has an additional field in the table that 'article' does not need to interact with called follow_up.
Most methods and validation is the same, but there are some tiny differences that could easily be done with if statements. The main problem I'm seeing is the URL, I want separate URLs like site.com/question and site.com/article but have them both interact with the same model, controller, and views.
How can this be done?
Use the urlManager component in the Yii config to set routes for /article and /question to go to the same controller, and then either use different actions or different parameters to differentiate between the two. Since you said they are almost identical, I would suggest different parameters and a single action as follows:
array(
...
'components' => array(
...
'urlManager' => array(
'question/<\d+:id>' => 'mycontroller/myaction/type/question/id/<id>',
'article/<\d+:id>' => 'mycontroller/myaction/type/article/id/<id>',
),
),
);
Of course you'll have to modify that for your needs, but that's the general setup. Look here for more information: http://www.yiiframework.com/doc/guide/1.1/en/topics.url

Lithium link routing

I am trying to create my first Lithium app and I'm getting a very odd error.
I have a line in my index view,
<td><?php echo $this->html->link($question->title, array('controller'=>'questions','action'=>'view','id'=>$question->id)); ?></td>
Which I would imagine would link to that records view, and using 'questions/view'.$question->id' it does, however, using an array url I get a fatal.
Fatal error: Uncaught exception 'lithium\net\http\RoutingException' with message 'No parameter match found for URL('controller' => 'questions', 'action' => 'view', 'id' => '1').' in /Applications/MAMP/htdocs/learning-lithium/libraries/lithium/net/http/Router.php on line 306
Which to me looks like the router is trying to match the url in the helper, and as it can't, for some reason, it's throwing an exception. Does anyone have any idea's why this is? I'm attacking Lithium from a CakePHP standpoint, so this seems odd to me.
The 'args' param is handled by the default routes and get passed in as arguments to your action method.
Try this:
<?=$this->html->link($question->title, array('Questions::view', 'args' => array($question->id))); ?>
To route it with an id param, you need to specify a route that looks for an id param via {:id}. Look in the default routes.php file for the "Database object routes" section. That has some examples which I'll copy below for completeness:
/**
* ### Database object routes
*
* The routes below are used primarily for accessing database objects, where `{:id}` corresponds to
* the primary key of the database object, and can be accessed in the controller as
* `$this->request->id`.
*
* If you're using a relational database, such as MySQL, SQLite or Postgres, where the primary key
* is an integer, uncomment the routes below to enable URLs like `/posts/edit/1138`,
* `/posts/view/1138.json`, etc.
*/
// Router::connect('/{:controller}/{:action}/{:id:\d+}.{:type}', array('id' => null));
// Router::connect('/{:controller}/{:action}/{:id:\d+}');
/**
* If you're using a document-oriented database, such as CouchDB or MongoDB, or another type of
* database which uses 24-character hexidecimal values as primary keys, uncomment the routes below.
*/
// Router::connect('/{:controller}/{:action}/{:id:[0-9a-f]{24}}.{:type}', array('id' => null));
// Router::connect('/{:controller}/{:action}/{:id:[0-9a-f]{24}}');
So you would need to uncomment one of those two sections depending on what format your ids take. They use regular expressions with the id param to make sure it doesn't match url arguments that aren't ids. Incidentally, the first route is setting the default value for id to null which doesn't exactly make sense to me because I don't think the route will ever match with a null value, but anyway, that is how you set default values for your params.
Note that if you do this, your controller action method needs to look like this:
public function view() {
$id = $this->request->id;
// or an alternative that does the same thing
// $id = $this->request->get("params::id");
// ... etc ...
}
The only way to get url pieces passed in as arguments to your controller action method is to use the 'args' param.
You're not using named parameters in your route, so just output the following in your view:
<?php echo $this->html->link($question->title, array('controller'=>'questions', 'action'=>'view', $question->id));?>
Your function signature in QuestionsController should simply be:
public function view($id) {}