Yii2 display data after join - yii2

I have joined 2 table, now I want to show the name of categories in field <th>Categories name</th>. How can I do that with <?php foreach ($posts as $post){ ?> ? Do i render like <?=$post->categories.name?> ? I'm stuck here.
Thank you.
My controller:
public function actionIndex()
{
$query = posts::find()->leftJoin('categories', 'posts.cate_id = categories.id');
$cates = Categories::find()->all();
$posts= $query->orderBy(['create_date' => SORT_DESC])->all();
$images = Images::find()->all();
$searchModel = new PostsSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'posts' => $posts,
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
'cates' => $cates,
'images' => $images,
]);
}
My view:
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Create Date</th>
</thead>
<tbody>
<?php foreach ($posts as $post){ ?>
<tr>
<td><?= $post->id ?></td>
<th><?= Html::a($post->name, ['post/view', 'id'=>$post->id]) ?></th>
<td><?= $post->create_date ?></td>
</tr>
<?php } ?>
</tbody>

Loop through the categories just as with posts. Its the same principle.
foreach($posts as $post)
foreach($post->categories as $category)
echo $category->name;
This is based on the assumption you have defined the proper relations in the model.
I.e. through foreign key:
public function getCategories()
{
return $this->hasMany(Category::className(), ['post_id' => 'id']);
}
You seem to have it the other way around. You can have category_id in post, but then its limited to one category. Unless, you store the ids in the field seperated by a delimeter. But that option requires a bit more work.

Related

Yii - Display Many to Many Attribute in DetailView

I have these three tables as shown below
courses and instructors tables are linked together in course_instructors
Model: Course
public function attributeLabels()
{
return [
'id' => Yii::t('course', 'Course ID'),
'course_name' => Yii::t('course', 'Course Name'),
'course_code' => Yii::t('course', 'Course Code'),
];
}
public function getCourseInstructors()
{
return $this->hasMany(CourseInstructors::className(), ['course_id' => 'id']);
}
and also
Model:Instructor
public function attributeLabels()
{
return [
'instructor_id' => Yii::t('ins', 'Instructor ID'),
'first_name' => Yii::t('ins', 'First Name'),
'middle_name' => Yii::t('ins', 'Middle Name'),
'last_name' => Yii::t('ins', 'Last Name'),
];
}
function getInstructorFullName()
{
return ($this->first_name." ".$this->middle_name." ".$this->last_name);
}
Then,
Model: CourseInstructors
public function attributeLabels()
{
return [
'id' => 'Course Instructor ID',
'course_id' => 'Course',
'instructor_id' => 'Course Instructor',
'remark' => 'Remark',
];
}
public function getCourses()
{
return $this->hasOne(Courses::className(), ['id' => 'course_id']);
}
public function getInstructors()
{
return $this->hasOne(Instructors::className(), ['instructor_id' => 'instructor_id']);
}
CourseControllers
public function actionView($id)
{
$model = $this->findModel($id);
$courseinstructors = $model->courseInstructors;
return $this->render('view', [
'model' => $model,
'courseinstructors' => $courseinstructors,
]);
}
Detail View: course
<?= DetailView::widget([
'model' => $model,
'options'=>['class'=>'table detail-view'],
'attributes' => [
'course_name',
'course_code',
],
]) ?>
<h2>Details</h2>
<table class="receipt-details table">
<tr>
<th>ID</th>
<th>Instructor Name</th>
<th>Remark</th>
</tr>
<?php foreach($model->courseInstructors as $courseInstructor) :?>
<tr>
<td><?= $courseInstructor->id ?></td>
<td><?= $courseInstructor->instructor_id ?></td>
<td><?= $courseInstructor->remark ?></td>
</tr>
<?php endforeach; ?>
</table>
From my Course Detail view, I want to display the instructor fullname
function getInstructorFullName()
{
return ($this->first_name." ".$this->middle_name." ".$this->last_name);
}
instead of the instructor_id in the Course Detail View
<td><?= $courseInstructor->instructor_id ?></td
This is what am getting
The question is how do I display the instructor full name in the course detail view instead of the instructor_id, since it is many to many.
You should use the framework power and consume the relations for the ActiveRecord models. Change your line from
<td><?= $courseInstructor->instructor_id ?></td>
to the following
<td><?= $courseInstructor->instructors->first_name.' '.$courseInstructor->instructors->last_name ?></td>
a better way would be to add the following method inside the model Instructors
public function getFullName(){
return $this->first_name.' '.$this->middle_name.' '.$this->last_name;
}
and then use it like
<td><?= $courseInstructor->instructors->fullName ?></td>
This should work in the Detail View:
<td><?= $courseInstructor->instructors->first_name ?></td> for first name.
<td><?= $courseInstructor->instructors->last_name ?></td> for last name.
You can join the name string to make a full name.
This comes from
public function getInstructors()
{
return $this->hasOne(Instructors::className(), ['instructor_id' => 'instructor_id']);
}
Let me know if it works for you.

YII2 Show data in view file according to user id

I am working on my collage project in which admin can create Employees(Teachers) and teachers can create students now my problem is that in index and view file any employee can see the total list of students recently added.
i want to put condition on view/index file so that specific teacher can view list of students created by him or her.
i have link between user table and Employee table (Created by & updated by)
Regards,
Yuvraj Verma
<section class="content doc-user-profile">
<div class="col-md-12 text-center">
</div>
</div>
<table class="table table-striped">
<tr>
<th><?= $info->getAttributeLabel('stu_unique_id') ?></th>
<td><?= Html::encode($info->stu_unique_id) ?></td>
</tr>
<tr>
<th><?php echo Yii::t('stu', 'Name'); ?></th>
<td><?= Html::encode($this->title) ?></td>
</tr>
<tr>
<th><?= $info->getAttributeLabel('stu_email_id') ?></th>
<td><?= Html::encode($info->stu_email_id) ?></td>
</tr>
<tr>
<th><?= $info->getAttributeLabel('stu_mobile_no') ?></th>
<td><?= $info->stu_mobile_no ?></td>
</tr>
<tr>
<th><?php echo Yii::t('stu', 'Status'); ?></th>
<td>
<?php if($model->is_status==0) : ?>
<span class="label label-success"><?php echo Yii::t('stu', 'Active'); ?></span>
<?php else : ?>
<span class="label label-danger"><?php echo Yii::t('stu', 'InActive'); ?></span>
<?php endif; ?>
</td>
</tr>
</table>
</div>
<div class="col-lg-9 profile-data">
<ul class="nav nav-tabs responsive" id = "profileTab">
<li class="active" id = "personal-tab"><i class="fa fa-street-view"></i> <?php echo Yii::t('stu', 'Personal'); ?></li>
</ul>
<div id='content' class="tab-content responsive">
<div class="tab-pane active" id="personal">
<?= $this->render('_tab_stu_personal', ['info' => $info, 'model' => $model]) ?>
</div>
</div>
</div>
</div> <!---End Row Div--->
Student Create Controller is as below:
public function actionCreate()
{
$model = new StuMaster();
$info = new StuInfo();
$user =new User();
$auth_assign = new AuthAssignment();
if (Yii::$app->request->isAjax) {
if($info->load(Yii::$app->request->post())) {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($info);
}
if($model->load(Yii::$app->request->post())) {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
}
$stud_uniq_no = \app\modules\student\models\StuInfo::find()->max('stu_unique_id');
$uniq_id = NULL;
if(empty($stud_uniq_no)) {
$uniq_id = $info->stu_unique_id = 1;
}
else {
$chk_id = StuInfo::find()->where(['stu_unique_id' => $stud_uniq_no])->exists();
if($chk_id)
$uniq_id = $stud_uniq_no + 1;
else
$uniq_id = $stud_uniq_no;
}
if ($model->load(Yii::$app->request->post()) && $info->load(Yii::$app->request->post()))
{
if (Yii::$app->request->isAjax) {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($info);
}
if (Yii::$app->request->isAjax) {
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
$model->attributes = $_POST['StuMaster'];
$info->attributes = $_POST['StuInfo'];
$info->stu_dob = Yii::$app->dateformatter->getDateFormat($_POST['StuInfo']['stu_dob']);
if(empty($_POST['StuInfo']['stu_email_id']))
$info->stu_email_id = NULL;
else
$info->stu_email_id = strtolower($_POST['StuInfo']['stu_email_id']);
$login_id = \app\models\Organization::find()->one()->org_stu_prefix.$uniq_id;
$user->user_login_id = $login_id;
$user->user_password = md5($user->user_login_id.$user->user_login_id);
$user->user_type = "S";
$user->created_by = Yii::$app->getid->getId();
$user->created_at = new \yii\db\Expression('NOW()');
if($info->save(false))
{
$user->save(false);
}
$model->stu_master_stu_info_id = $info->stu_info_id;
$model->stu_master_user_id = $user->user_id;
$model->created_by = Yii::$app->getid->getId();
$model->created_at = new \yii\db\Expression('NOW()');
$model->save(false);
$s_info = StuInfo::findOne($model->stu_master_stu_info_id);
$s_info->stu_info_stu_master_id = $model->stu_master_id;
$s_info->save(false);
$auth_assign->item_name = 'Student';
$auth_assign->user_id = $user->user_id;
$auth_assign->created_at = date_format(date_create(),'U');
$auth_assign->save(false);
if ($model->save()) {
return $this->redirect(['view', 'id'=>$model->stu_master_id]);
}
else
return $this->render('create', ['model' => $model, 'info' => $info, 'uniq_id'=>$uniq_id]);
} else {
return $this->render('create', [
'model' => $model, 'info' => $info, 'uniq_id'=>$uniq_id
]);
}
}
In your "modelSearch"'s search function add a created_by filter:
public function search($params)
{
$query = StuInfo::find();
...
$query->andFilterWhere(['created_by' => Yii::$app->user->identity->id]);
....
}
For your view(actionView) you could check if the record was created by the logged in user before render.
This would get complex with time so i recommend using authorization - Yii2 Access Control and Authorization
Your create action is ok.
You have to put restriction in index/view action of your controller
Your index action should be like this
public function actionIndex()
{
$searchModel = new StudentSearch();
$query = Student::find()->where(['teacher_id'=>$logged_teacher_id_from_session]);
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => [
'pageSize' => 20,
],
'sort' => [
'defaultOrder' => [
'student_id' => SORT_ASC,
]
],
]);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
In this case teacher who is logged in can see only his/ student

Yii2 no result message without using gridview

My controller:
public function actionResults()
{
$query = User::find();
$admins = $query->orderBy('id')->andWhere('role_id = 1')->all();
$searchModel = new AdminSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('results', [
'admins' => $admins,
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
]);
}
Result view:
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Create Date</th>
</thead>
<tbody>
<?php foreach ($dataProvider->models as $model){ ?>
<tr>
<td><?= $model->username; ?></td>
<td><?=$model->fullname; ?></td>
<td><?=$model->email; ?></td>
</tr>
I don't want to use Gridview to so I render the result out like that, but don't know how to throw a no result message.
Please help me.
Thanks
Use php isset() and empty() funtions to check is there is data in the array
if(isset($dataProvider->models) && !empty($dataProvider->models)){
//do you foreach loop here
}else {
echo 'empty';
}

Multiple Check boxes in cake php

I have a list of bookings and I want to delete them using multiple checkboxes. Here is my code:
foreach ($bookings as $booking): ?>
<tr>
<td><?php echo h($booking['Booking']['first_name']); ?> </td>
<td><?php echo h($booking['Booking']['surname']); ?> </td>
<td><?php echo h($booking['Booking']['created']); ?> </td>
<td><?php echo $this->Form-> checkbox('Bookings.ID.['.$booking['Booking']['ID'].']',
array('value' => $booking['Booking']['ID']));?></td>
</tr>
<?php endforeach; ?>
and in my controller I use this function to delete the selected bookings:
public function deletebooking(){
$bookings = $this->Booking->find('all');
$this->set('bookings',$bookings);
if(!empty($this->data)){
foreach($this->data[Bookings] as $key => $value){
if($value != 0){
$this->Booking->delete($value);
$this->redirect(array('action' => 'index'));
}
}
}
}
Can anyone tell me why it is not working?
Change your input field to the following:
foreach ($bookings as $booking): ?>
<td>
<?php echo $this->Form->checkbox('bookingids',
array(
'value' => $booking['Booking']['ID'],
'name' => 'data[Booking][bookingids][]',
));?>
</td>
Notice the empty [] in the name value. This will create a new index of that array. In your controller you would access it like this:
if(!empty($this->data)) :
foreach($this->data['Bookings']['bookingids'] as $key => $value):
$data = array();
$data['Booking']['id'] = $value;
$this->Booking->delete($data);
endforeach;
$this->redirect(array('action' => 'index'));
endif;

Adding another field from another controller into an array

Hey at the moment we have an arrray selecting all from one table (relationship) and we need to put account_name from the Accounts table in that array. How would we do so?
Our Relationship table has (id, receiver_id, sender_id, active, expiry_date). Receiver_id and sender_id both are the foreign keys for account_id.
At the moment it works fine but prints the ids of the receiver and sender, we want the account_name from Account table to be there instead.
Here is our function, view and model:
Function:
//retrieve Account Id of current User
$accountid=$this->Auth->user('account_id');
//Conditions
$conditions=array("OR"=> array(
'Relationship.sender_id' => $accountid,
'Relationship.receiver_id' => $accountid));
//Find all Invoices where receiver_id = accountid
$relationships=$this->Relationship->find('all', array(
'conditions' => $conditions));
debug($relationships);
$this->set('accountid', $accountid);
$this->set('relationship', $relationships);
}
View:
<table>
<tr>
<th>Relationship #</th>
<th>Sender</th>
<th>Receiver</th>
<th>Expiry Date</th>
<th>Status</th>
</tr>
<?php foreach($relationship as $relationships):?>
<?php
if($relationships['Relationship']['active']==1)
{
$status = 'Active';
}
else if($relationships['Relationship']['active']==0)
{
$status = 'Not Active';
}
?>
<tr>
<td align='center'><?php echo $relationships['Relationship']['id']; ?></td>
<td align='center'><?php echo $relationships['Relationship']['sender_id']; ?></td>
<td align='center'><?php echo $relationships['Relationship']['receiver_id']; ?></td>
<td align='center'><?php echo date('d.m.Y', strtotime($relationships['Relationship']['expiry_date'])); ?></td>
<td align='center'><?php echo $status ?></td>
</tr>
<?php endforeach; ?>
</table>
Relationship Model:
class Relationship extends AppModel
{
var $name = 'Relationship';
public $useTable = 'relationships';
public $primaryKey = 'id';
/*
public $hasMany = array(
'Invoice' =>
array(
'className' => 'Invoice',
'joinTable' => 'invoice',
'foreignKey' => 'invoice_id'));*/
//fix this code
public $belongsTo = array(
'User' =>array(
'className' => 'User',
'foreignKey' =>'receiver_id',
'associationForeignKey' => 'accounts_id',
));
var $validate = array(
'date' => array(
'rule' => array(
'datevalidation',
'systemDate'
),
'message' => 'Current Date and System Date is mismatched'
),
'receiver_id' => array(
'userExists' => array(
'rule' => array(
'userExists',
),
'message' => 'That username doesnt exist.'
),
),
);
function datevalidation($field = array(), $compare_field = null)
{
if ($field['date'] > $compare_field)
return TRUE;
else
return FALSE;
}
function accountExists($check)
{
$accountExists = $this->Account->find('count', array('conditions' => array('Account.id'=>$check)));
if ($accountExists == 1) {
return TRUE;
}
else
return FALSE;
}
}
Note it's not another field from another "controller" but rather another model.
There are a number of ways you could do this:
You could use joins on the find() method: http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#joining-tables
Or you could probably also use bindModel(), which I find particularly useful: http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#creating-and-destroying-associations-on-the-fly
Scour the cookbook! Although sometimes tedious, it really is extremely helpful. I had to hack around quite a bit before I got a decent understanding of how Cake works.