YII dropdown menu, 2 models - php

I am new in PHP and yii framework so I need some help with the dropdown menu. In my database I have 2 tables - Category - id, name and News - id, title, content, category_id. How could I make the relation between these two controllers? When I post news I must choose the category from drop down menu. I'm sorry for the stupid question but I can't do it at this moment.

Simply place this in your News model:
/**
* #return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'category' => array(self::BELONGS_TO, 'Category', 'category_id'),
);
}
and this in your Category model:
/**
* #return array relational rules.
*/
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'newsItems' => array(self::HAS_MANY, 'News', 'category_id'),
);
}
whenever you have an instance of your Category, you can refer to your multiple news items like so:
$category = Category::model()->findByPk(1);
$category->newsItems; //an array of News objects
and you can refer back to the category like so:
$news = News::model()->findByPk(1);
$category = $news->category; //a Category object

I think your asking about how to show all the categories for selection when your creating a news item. In your form for creating the news object you need something like:
$cats = Category::model()->findAll();
$cats = CHtml::listData($cats, 'id', 'name');
$form->dropDownList($model, 'category', $cats);
For the relation between them and accessing it afterwards see Benjamin Bytheway's answer

You can do what paystey wrote all in one line like this:
<?php echo $form->dropDownList($model,'Category', CHtml::listData($CategoryModel::model()->findAll(array('order'=>'Text ASC')), 'CategoryID', 'Text'), array('empty'=> ' -- Select A Category -- '));?>
The last parameter of the list data is just what should display when the page loads.

Related

How to display value from other table using primary key

I have implemented my project in Yii. I displaying search results in view part.
I wrote a search query for fetching the results from one table which is Recipe.
In this table name, course_id, cuisinename,type, colorie_count respectively, course_id,cuisinename, type are columns respectively.
In my controller i write code like this:
$result="SELECT * FROM recipe WHERE name LIKE '%$name%' AND `cuisinename` LIKE '$cuisine1%' AND course_id LIKE '%$course1%' AND `type` LIKE '%$type1%' AND `calorie_count` LIKE '%$calorie1%' ORDER BY recipe_id DESC LIMIT 15";
values are getting. if i give condition based to display the search result text. not displaying all name.
but those are displaying based on names.
I added below my view part condition and code:
$query= Course::model()->find("course_id=$as1");
$course2=$query->course_name;
$query1= Cuisine::model()->find("id=$as4");
$cuisine2=$query1->cuisinename;
$query3= RecipeType::model()->find("id=$as3");
$type2=$query3->recipeType_name;
<?php echo '<p align="center"> Showing results for&nbsp:&nbsp'.'Name'.$getval.',&nbsp'.'Course-'.$course2.',&nbsp'.'Cuisine-'.$cuisine2.',&nbsp'.'Type-'.$type2;',&nbsp';'</p>';
echo ',&nbsp'.'Calories-'.$calorie;
?>
You need to create relations between tables look there. For Recipe model it should be
public function relations()
{
return array(
'cuisine'=>array(self::BELONGS_TO, 'Cuisine', 'cuisine_id'),
'type'=>array(self::BELONGS_TO, 'RecipeType', 'type_id'),
);
}
Then you can get values as $model->cuisine->name. If you don't understand creating relations, generate models (it tables must be correct foreign keys) with gii.
check this article: http://www.yiiframework.com/doc/guide/1.1/en/database.arr about relations in AR
class Recipe extends CActiveRecord
{
......
public function relations()
{
return array(
'course'=>array(self::BELONGS_TO, 'Course', 'course_id'),
'cuisine'=>array(self::BELONGS_TO, 'Cuisine', 'cuisine_id'),
'type'=>array(self::BELONGS_TO, 'RecipeType', 'type_id'),
);
}
}
and related Models
class RecipeType extends CActiveRecord
{
......
public function relations()
{
return array(
'recipes'=>array(self::HAS_MANY, 'Recipe ', 'type_id'),
);
}
}
and your search query will be smth like this in controller file:
$criteria=new CDbCriteria;
$criteria->with=array(
'course',
'cuisine',
'type',
);
$criteria->addCondition('course.course_id = :filter_course'); // for ID compares
$criteria->addSearchCondition('cuisine.name', $cuisinename) //for LIKE compares
...
$criteria->params = array(':filter_course' => intval($course1));
$searchResults = Receipe::model()->findAll($criteria);
and in your view you can get related tables values:
foreach ($searchResults as $result){
echo $result->cuisine->name;
}
check also http://www.yiiframework.com/doc/api/1.1/CDbCriteria for details
you can also use this $criteria to create DataProdier for CListView or CGridView helpers in your view file
$dataProvider=new CActiveDataProvider( Receipe::model()->cache(5000),
array (
'criteria' => $criteria,
'pagination' => array (
'pageSize' => 10,
)
)
);
$this->render('search',array(
'dataProvider'=>$dataProvider
));
http://www.yiiframework.com/doc/api/1.1/CListView/
http://www.yiiframework.com/doc/api/1.1/CGridView

cakephp paginate - sort records per categories (has different categories per record)

I'm trying to sort records per categories and each record has one or more categories if the user has categories he likes.. If none, then just display all records..
Example, if a record has Food Category and the user signed in happens to have selected Food as one of his interests then the list of records displayed will be sorted having the records under Food category on top of the list..
I have
$this->Steplist->virtualFields['in_like'] = "IF(Record.category_id IN ($interests), 0, 1)";
$order["in_like"] = 'asc';
then
'order' => $order
for $this->Paginator->settings
then
int for the category_id
Now, instead of having 1 category for each record, it has to be changed to several categories. To avoid changing so much since the site is complete now, I simply change the category_id (int) to categories (varchar) with category ids separated by commas.. so instead of 5 for example, it can now be 3,5,7 if there are several categories attached to the record..
I tried to change the virtual field condition to:
$this->Steplist->virtualFields['in_like'] = "IF(Record.categories IN ($interests), 0, 1)";
but the result is not correct.
How do I do this instead (cakephp 2.4.3)?
This will work on settigns pagination.
class RecipesController extends AppController {
public $components = array('Paginator');
public function list_recipes() {
$paginate = array(
'limit' => 25,
'order' => array(
'Post.title' => 'asc'
)
);
$this->Paginator->settings = $paginate;
// similar to findAll(), but fetches paged results
$data = $this->Paginator->paginate('Recipe');
$this->set('data', $data);
}
}
http://book.cakephp.org/2.0/en/core-libraries/components/pagination.html
Limitations of virtualFields
But in general if you are using virtual fields: The implementation of virtualFields has a few limitations. First you cannot use virtualFields on associated models for conditions, order, or fields arrays. Doing so will generally result in an SQL error as the fields are not replaced by the ORM. This is because it difficult to estimate the depth at which an associated model might be found.
You can use asort() or sort() after retrieving your data

Order data based on count of related table data

I have Two diff tables as given below:
users and posts
Need data from user's table order by count of posts table
Relationship is defined as:
User Model:
public $hasMany = array('Post');
Post Model
Public $belongsTo = array('User');
counterCache - Cache your count()
This function helps you cache the count of related data. Instead of counting the records manually via find('count'), the model itself tracks any addition/deleting towards the associated $hasMany model and increases/decreases a dedicated integer field within the parent model table.
The name of the field consists of the singular model name followed by a underscore and the word “count”:
my_model_count
Let’s say you have a model called ImageComment and a model called Image, you would add a new INT-field to the image table and name it image_comment_count.
Once you have added the counter field you are good to go. Activate counter-cache in your association by adding a counterCache key and set the value to true:
<?php
class Image extends AppModel {
public $belongsTo = array(
'ImageAlbum' => array('counterCache' => true)
);
}
From now on, every time you add or remove a Image associated to ImageAlbum, the number within image_count is adjusted automatically.
You can also specify counterScope. It allows you to specify a simple condition which tells the model when to update (or when not to, depending on how you look at it) the counter value.
Using our Image model example, we can specify it like so:
<?php
class Image extends AppModel {
public $belongsTo = array(
'ImageAlbum' => array(
'counterCache' => true,
'counterScope' => array('Image.active' => 1) // only count if "Image" is active = 1
));
}

How to display differnt field other than id when using Associations and baking cake

I'm using Associations to Link Models together in CakePHP.
I have a Player model that is linked to a Statistic model using a $hasMany relationship. So basically one player can have many statistics.
After I set up these relationships, I use cake bake to generate the controllers and views for both the Player and Statistic models.
Everything works fine and works as expected, but when I go to add a statistic using the add template, the player_id is used as the association.
My question is how do I set up the model to use the player_id as the association but use something like the player's first and last name as the drop down menu in the add template.
Currently if I go to add a new statistic, I get a drop down box that called "Player" that lists all of the player id's but what I want is for the player's first_name and last_name to be in that drop down box instead of the id. I realize that I can modify the controller or template to accomplish this, but I Want to know if I can do this while setting up the model so that cake bake can take care of it.
Player Model:
<?php
class Player extends AppModel {
public $name = 'Player';
public $belongsTo = array(
'School' => array(
'className' => 'School',
'foreignKey' => 'school_id'
)
);
public $hasMany = 'Statistic';
}
Statistic Model:
<?php
class Statistic extends AppModel {
public $name = 'Statistic';
public $belongsTo = array(
'Player' => array(
'className' => 'Player',
'foreignKey' => 'player_id'
)
);
}
Players Table
`id|school_id|first_name|last_name|number|position
Cake uses the model's displayField attribute when choosing the default columns for a list. If none is defined for the model it will look for name or title. So in your model you can use:
public $displayField = 'first_name';
This will display the player's first name in the list.
If you want the display field to be the concatenation of two fields, you can use a virtual field in the model like so:
public $virtualFields = array(
'name' => "TRIM(CONCAT(Player.first_name, ' ', Player.last_name))"
);
Note the above works for Mysql. For another kind of database you will need to adjust the syntax. For example, for Sqlite it would be:
TRIM(Player.first_name || ' ' || Player.last_name)
Then add in your model:
public $displayField = 'name';

CLEARER UPDATE: self-referencing relationship is not working with datamapper in codeigniter

I read the documentation several times.
This is table structure:
categories:
id controller user_id approved enabled_comments
categories_related_categories
id category_id related_category_id
categories_zones
id category_id zone_id
This is my expectations:
I am trying to save multiple relations:
Expectations:
New Category record is created (let’s call it subcategory but in reality no where is subcategory mentioned in database)
The new category gets auto incremented to categories table and is given values for controller, user_id, enabled_comments fields passed from the query string of a http post request via the php form
An existing category is searched (let’s call it parent category but in reality no where is parent category mentioned in the database)
A new record is written to the categories_related_categories table where category_id refers to the primary key of the new category created and related_category_id refers to the id of the existing category we searched. Hence we create a many to many self-referencing relationship where a subcategory can have many categories and a parent category can have many subcategories
A category can have many zones and a zone can have many categories. A user has the option to select one or many zones from a multiselect dropdown. If user selects two zones (each of them have a name using a name field like ‘main’ or ‘panel’), for example, then when the new category is written to the database, not only is a parent category established with it in the categories_related_categories table, but a many to many is established in the categories_zones table, where two records are created (if the user selects two options from multiselect), one record has the primary key of the new category with the one zone record selected from multiselect and the second record again has the primary key of the new cateogry with the other zone record selected from the multiselect.
So it’s the subcategory that has the relation with the parent and the zone(s):
This is the code:
public function create(){
$vanity_url = new VanityUrl();
$vanity_url->where('url',$this->uri->segment(2))->get();
$blogger = new User();
$blogger->where('id',$vanity_url->user_id)->get();
/* self-referencing many to many */
$subcategory = new Category; //subcategory - we create a new one
$subcategory->controller = $this->input->post('controller');
$subcategory->enable_comments = $this->input->post('approved');
$subcategory->user_id = $this->current_user()->id;
$parent_category = new Category(); //parent category - we find via a search in the table
$parent_category->where('controller',$this->input->post('parent_controller'))->get();
// $subcategory->save($parent_category);
/* many to many - category has many zones :: zone has many categories */
$zone = new Zone();
$zones = $this->input->post('zones');
foreach($zones as $z){
switch($z){
case 'main':
$zone->where('name',$z);
break;
case 'panel':
$zone->where('name',$z);
break;
}
}
$zone->get();
$subcategory->save($parent_category,$zone);
}
I get the following error with the above code (although the categories_zones table does get written to):
A PHP Error was encountered
Severity: Warning
Message: Illegal offset type in isset or empty
Filename: libraries/Datamapper.php
Line Number: 4151
I try this:
$subcategory->save_relation($parent_category,$zone);
But I get this error:
An Error Was Encountered
Unable to relate category with relation.
Then I try the example in this link: http://datamapper.wanwizard.eu/pages/save.html
$subcategory->save(array($parent_category,$zone));
THat will write to categories_related_categories table but not categories_zones table.
My category and zone model contains this:
class Category extends DataMapper {
var $has_one = array("user");
public $has_many = array(
'related_category' => array(
'class' => 'category',
'other_field' => 'category',
// 'reciprocal' => TRUE
),
'category' => array(
'other_field' => 'related_category',
),
'post',
'zone'
);
}
class Zone extends DataMapper {
var $has_many = array("category");
}
My temporary solution is the last comment (as of now):
http://codeigniter.com/forums/viewthread/186054/
I know this is an old question, but I'll try helping out for anyone else with this question.
When you save multiple relationships, you can (and must on a self-referencing relationship) use a relationship_key that you defined in the model as the key in the array:
$subcategory->save(
array(
'category' => $parent_category,
'zone' => $zone
)
);
Take a look at the bottom of this page for the docs and example:
http://datamapper.wanwizard.eu/pages/save.html

Categories