I wish to list some Categories name on my layout main.php page.
Since the layout doesn't have any associated controller or model, I wish to create a static method like this on Category model:
public static function getHeaderModels()
{
// get all models here
return $models;
}
and then in the main layout
<?php
$models = Category::getHeaderModels();
foreach($models as $model)
{
// ....
}
?>
My question is a very basic one:
How can I retrieve those category names from the model ?
Here is the full model:
class Category extends CActiveRecord {
public static function model($className=__CLASS__) {
return parent::model($className);
}
public function tableName() {
return 'category';
}
public function rules() {
return array(
array('parent_id', 'numerical', 'integerOnly' => true),
array('name', 'length', 'max' => 255),
array('id, parent_id, name', 'safe', 'on' => 'search'),
);
}
public function relations() {
return array(
'users' => array(self::MANY_MANY, 'User', 'categories(category_id, user_id)'),
);
}
public function scopes()
{
return array(
'toplevel'=>array(
'condition' => 'parent_id IS NULL'
),
);
}
public function attributeLabels() {
$id = Yii::t('trans', 'ID');
$parentId = Yii::t('trans', 'Parent');
$name = Yii::t('trans', 'Name');
return array(
'id' => $id,
'parent_id' => $parentId,
'name' => $name,
);
}
public function search() {
$criteria = new CDbCriteria;
$criteria->compare('id', $this->id);
$criteria->compare('parent_id', $this->parent_id);
$criteria->compare('name', $this->name, true);
return new CActiveDataProvider(get_class($this), array(
'criteria' => $criteria,
));
}
public static function getHeaderModels() {
//what sintax should I use to retrieve the models here ?
return $models;
}
May be this answer can help you. First you must create a Widget so you can use it more effectively.
First Create a new widget. Let say the name is CategoryWidget. Put this widget under components directory protected/components.
class CategoryWidget extends CWidget {
public function run() {
$models = Category::model()->findAll();
$this->render('category', array(
'models'=>$models
));
}
}
Then create a view for this widget. The file name is category.php.
Put it under protected/components/views
category.php
<?php if($models != null): ?>
<ul>
<?php foreach($models as $model): ?>
<li><?php echo $model->name; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
Then call this widget from your main layout.
main.php
// your code ...
<?php $this->widget('CategoryWidget') ?>
...
If I'm not mistaken, you can also pass any variable available in a view, on to the layout.
You just do it from the view that has your variable.
This is the catch: you need to declare the variable which will receive your value, in the controller, like this:
<?php
class MyController extends Controller
{
public $myvariable;
After this, you will assign your model or whatever to this public variable inside your view,
like this:
$this->myvariable = $modeldata;
After you have assigned your model data to controller's public attribute,
you can easily display it inside your layout e.g.
echo $this->myvariable;
Yii already does this by assigning menu items to column2 sidebar menu, from view, like this:
$this->menu=array(
array('label'=>'List Item', 'url'=>array('index')),
array('label'=>'Manage Item', 'url'=>array('admin')),
);
You can see it in all create/update views that gii crud creates.
Related
Im a designer that i´m taking my first steps on the programing área, mostly on PHP / MySQL. Past week i need to add a blog section on a page made with code igniter.
I make the secction that show all post in order (title and published date). I made a view that takes the id to show the content. But i can`t echo any of the variables.
When i use var_dump or print and it takes all the variables without any problem.
Did i miss somehting? :(
Thank you.
Model:
class blog extends CI_Model {
public function get($id){
$this->db->select('id, title, description, icon, uri, published_at');
$this->db->from('blogs');
$this->db->where('id', $id);
$query = $this->db->get();
$data = $query->result();
return $query->result();
if(!empty($data)){
return $this->make_groups($data);
}
}
}
Controller:
Class Pages extends CI_Controller {
public function blog_detail($id) {
$this->load->model('blog');
if($data = $this->blog->get($id)) {
$this->load->model('blog');
$this->data['blog_menu'] = TRUE;
$this->data['blog'] = $data;
$this->data['og'] = array(
'description' => 'INFO',
'image' => site_url('assets/images/og/blog.png')
);
# layout config
$this->layout->add_css(site_url('assets/css/blog.css'));
$this->layout->title_for_layout = "TITLE";
$this->layout->meta = array(
array('name' => 'description', 'content' => 'DETAIL'),
array('name' => 'keywords', 'content' => 'KEYWORDS'),
);
$this->layout->render('pages/blog_detail/index', $this->data);
}
}
}
View:
<?php var_dump($this->data);
echo $blog->published_at; ?>
On your model you are not returning the result
Check that the filenames and class names only have the first letter upper case.
Blog_model.php
class Blog_model extends CI_Model {
public function get($id) {
$this->db->select('id, title, description, icon, uri, published_at');
$this->db->from('blogs');
$this->db->where('id', $id);
$query = $this->db->get();
return $query->row_array();
}
}
Controller
controllers > Pages.php
class Pages extends CI_Controller {
public function __construct() {
parent::__construct();
$this->load->model('blog_model');
}
public function blog_detail($id) {
$blog_data = $this->blog_model->get($id);
if($blog_data)) {
$this->data['blog_menu'] = TRUE;
$this->data['published_at'] = $blog_data['published_at'];
var_dump($blog_data);
$this->data['og'] = array(
'description' => 'INFO',
'image' => site_url('assets/images/og/blog.png')
);
# layout config
$this->layout->add_css(site_url('assets/css/blog.css'));
$this->layout->title_for_layout = "TITLE";
$this->layout->meta = array(
array('name' => 'description', 'content' => 'DETAIL'),
array('name' => 'keywords', 'content' => 'KEYWORDS'),
);
$this->layout->render('pages/blog_detail/index', $this->data);
}
}
}
View
<?php echo $published_at;?>
I have some custom routes in my system:
---
Name: mysiteroutes
---
Director:
rules:
'create//$Action': 'CreateController'
Which has a custom controller to create a form:
class CreateController extends Page_Controller{
private static $allowed_actions = array(
'submit'
);
public function link($action = null) {
return $this->join_links('create/', $action);
}
public function index() {
$form = Form::create(
$this,
'',
FieldList::create(
TextField::create('Name', 'Name'),
$upload = new UploadField('Upload', 'Upload')
),
FieldList::create(
FormAction::create('submit', 'Submit')->setAttribute('class', 'btn btn-success')
),
RequiredFields::create('Name')
);
if($this->request->isPost()) return $form;
return $this->customise(array('Form'=>$form))->renderWith(array("Create", "Page"));
}
public function submit($data, $form = null) {
$params = $this->getRequest()->params();
var_dump($params);
}
}
When I try and upload something it calls Field() on my controller and then fails as it's not there. I can add it and it calls it correctly however I have no idea what to put in it. I've looked through the Field() function in UploadField.php however there is a lot of code there which I probably shouldn't just copy.
How should I manage the upload of the file in my custom controller or can I forward it to the core framework somehow?
UploadField expects to have a route based on the Form name, in your case ''.
If you would change the name of the form to form it would call form/field/Upload/upload. What this does is get the form, then get the field with the name Upload and call the method upload on that class.
Unfortunately, the way you are using the form (which I showed you in an earlier answer :( ) does not support this.
We could solve it like this;
CreateController
class CreateController extends Page_Controller
{
private static $allowed_actions = [
'form'
];
public function link($action = null)
{
return $this->join_links('create', $action);
}
public function index()
{
return $this->renderWith(array("Create", "Page"));
}
public function form()
{
return UploadForm::create($this, 'form', 'submit');
}
public function submit($data, $form = null)
{
$params = $this->getRequest()->params();
var_dump($params);
}
}
Form
// create an extra class for the form to keep your controller clean
class UploadForm extends Form
{
public function __construct($controller, $name, $action)
{
$fields = FieldList::create(
TextField::create('Name', 'Name'),
UploadField::create('Upload', 'Upload')
);
$actions = FieldList::create(
FormAction::create($action, 'Submit')
->setAttribute('class', 'btn btn-success')
);
$validator = RequiredFields::create('Name');
parent::__construct($controller, $name, $fields, $actions, $validator);
}
}
I want to make a custom widget like one of the examples that yii brings (blog), and the custom widget i want to make is the one called "RecentPosts", but for my page i'm going to call it "RecentTasks", so i just want to get the firsts 4 tasks on my database SQLite(almos like "recentPost" does).
in my column2:
<?php /* #var $this Controller */ ?>
<?php $this->beginContent('//layouts/main'); ?>
<div class="col-xs-12 col-sm-9">
<div id="content">
<?php echo $content; ?>
</div><!-- content -->
</div>
<div id="sidebar" class="col-xs-6 col-sm-3 sidebar-offcanvas" role="navigation">
<div class="list-group">
<?php
// $this->beginWidget('zii.widgets.CPortlet', array(
// 'title'=>'Operations',
// ));
$this->widget('zii.widgets.CMenu', array(
'items'=>$this->menu,
'htmlOptions'=>array('class'=>'nav nav-pills nav-stacked'),
));
// $this->endWidget();
?>
<?php
$this->widget('recentTasks', array(
'maxTasks'=>10
));
?>
</div>
</div>
<?php $this->endContent(); ?>
in my custom widget inside components:
<?php
Yii::import('zii.widgets.CPortlet');
class RecentTasks extends CPortlet
{
public $title = 'Recent Tasks';
public $maxTasks = 10;
public function getRecentTasks()
{
return Task::model()->findRecentTasks($this->maxTasks);
}
protected function renderContent()
{
$this->render('recentTasks');
}
}
my model:
<?php
class Task extends CActiveRecord
{
/**
* #return string the associated database table name
*/
public function tableName()
{
return 'task';
}
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('Name, Status, Project_id, User_id', 'required'),
array('Status, Project_id, User_id', 'numerical', 'integerOnly'=>true),
array('Name, Create_time, Update_time, Assigned', 'length', 'max'=>45),
array('Description, Tags', 'safe'),
// The following rule is used by search().
// #todo Please remove those attributes that should not be searched.
array('id, Name, Description, Status, Create_time, Update_time, Tags, Project_id, User_id, Assigned', 'safe', 'on'=>'search'),
);
}
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(
'comments' => array(self::HAS_MANY, 'Comment', 'Task_id'),
'project' => array(self::BELONGS_TO, 'Project', 'Project_id'),
'user' => array(self::BELONGS_TO, 'User', 'User_id'),
);
}
public function attributeLabels()
{
return array(
'id' => 'ID',
'Name' => 'Name',
'Description' => 'Description',
'Status' => 'Status',
'Create_time' => 'Create Time',
'Update_time' => 'Update Time',
'Tags' => 'Tags',
'Project_id' => 'Project',
'User_id' => 'User',
'Assigned' => 'Assigned',
);
}
public function findRecentTasks($limit=10)
{
$this->findAll();
}
public function search()
{
// #todo Please modify the following code to remove attributes that should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('Name',$this->Name,true);
$criteria->compare('Description',$this->Description,true);
$criteria->compare('Status',$this->Status);
$criteria->compare('Create_time',$this->Create_time,true);
$criteria->compare('Update_time',$this->Update_time,true);
$criteria->compare('Tags',$this->Tags,true);
$criteria->compare('Project_id',$this->Project_id);
$criteria->compare('User_id',$this->User_id);
$criteria->compare('Assigned',$this->Assigned,true);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}
in the view of the widget im just making var_dump($this->getRecentTasks());
i haven't figure out the problem but for now its just returning NULL. I followed almost the exact same steps made on the example page in yii
Try this:
// location: /protected/components/RecentTasks.php
class RecentTasks extends CWidget
{
public $title = 'Recent Tasks';
public $maxTasks = 10;
/**
* Is called when $this->beginWidget() is called
*/
public function init()
{
}
/**
* Is called when $this->endWidget() is called
*/
public function run()
{
// render /protected/components/views/recentTasks.php
$this->render('recentTasks', array(
'models'=>$this->getRecentTasks($this->maxTasks)
));
}
public function getRecentTasks()
{
return Task::model()->findRecentTasks($this->maxTasks);
}
}
Call the widget like so in your view or layout file (with a capital):
$this->widget('RecentTasks', array(
'maxTasks'=>10
));
Then you can use $models in the view to show the tasks.
Also see: http://www.yiiframework.com/doc/guide/1.1/en/basics.view#widget
EDIT:
Seems the problem is in your findRecentTasks() method, add return before the findAll(). I also added the code to apply the limit and for conditions may you need that in the future.
public function findRecentTasks($limit=10)
{
return $this->findAll(array(
// 'condition'=>'id = :id',
// 'params' => array('id'=>$id),
'limit'=>$limit
));
}
In the form when I echo the session value it is prompted no errors, but when I try to save it on the database in the model the value is not saved.
Here is my view:
(I just posted here what I think is needed.)
<?php
$userid = Yii::app()->session['iduser'];
echo $userid;
?>
Here is my controller:
The contentid, title and content are saved in the database only the userid is my problem. In my database I set the userid as int(11) not null
public function actionContent(){
$model=new ContentForm;
if(isset($_POST['ContentForm'])) {
$model->attributes=$_POST['ContentForm'];
if($model->save())
$this->redirect(array('content','contentid'=>$model->contentid));
$this->redirect(array('content','title'=>$model->title));
$this->redirect(array('content','content'=>$model->content));
$this->redirect(array('content','userid'=>$model->userid));
}
$this->render('content',array('model'=>$model));
}
And here is my model:
<?php
class ContentForm extends CActiveRecord{
public $content;
public $title;
public $userid;
public function tableName(){
return 'tbl_content';
}
public function attributeLabels(){
return array(
'contentid' => 'contentid',
'content' => 'content',
'title' => 'title',
'userid' => 'userid',
);
}
public function rules(){
return array(
array('content, title, userid', 'safe'),
);
}
}
Your user id Stored in Session it can accessed anywhere in the MVC
Try this on your controller
public function actionContent(){
$model=new ContentForm;
if(isset($_POST['ContentForm'])) {
$model->attributes=$_POST['ContentForm'];//The post values
$model->userid=Yii::app()->session['iduser'];
if($model->save())
$this->redirect(array('content','contentid'=>$model->contentid));
//$this->redirect(array('content','title'=>$model->title));
//$this->redirect(array('content','content'=>$model->content)); //Why this to many redirects here the first redirect only works here
//$this->redirect(array('content','userid'=>$model->userid));
}
$this->render('content',array('model'=>$model));
}
I have the following model:
class Person
{
public $name;
function __Construct( $name )
{
$this->name = $name;
}
}
I have the following controller:
class NavigationController extends Controller
{
public function indexAction()
{
$people = array(
new Person("James"),
new Person("Bob")
);
return $this->render('FrameworkBundle:Navigation:index.html.php', $people);
}
}
How do I get access to the model array in the view. Is there a way to access the model directly or do I have to assign a property like so:?
class NavigationController extends Controller
{
public function indexAction()
{
$people = array(
new Person("James"),
new Person("Bob")
);
return $this->render('FrameworkBundle:Navigation:index.html.php', array( "model" => $people ) );
}
}
View:
<?php
foreach( $model as $person )
{
echo $person->title;
}
?>
The problem with the above will be that it can be changed by a user to
return $this->render( 'FrameworkBundle:Navigation:index.html.php', array( "marybloomingpoppin" => $people ) );
With the example view you used, you already had the correct implementation:
class NavigationController extends Controller
{
public function indexAction()
{
$people = array(
new Person("James"),
new Person("Bob")
);
return $this->render('FrameworkBundle:Navigation:index.html.php', array( "model" => $people ) );
}
}
You mentioned the concern that somebody could change the assignment in the controller, but this is something you always have if somebody changes the name of a variable only in one place and not in all. So I don't think this is an issue.