I am starting to learn Yii framework so I am a beginner. I am struggling. I want to fetch the data from database using yii2 framework. This is my controller
public function actionView()
{
$this->view->title = 'List Hotels';
$items = ArrayHelper::map(Hotel::find()->all(), 'id', 'name');
return $this->render('index', [
'items' => $items,
]);
}
In my view file, I used the fetched data as below;
<?php
/* #var $this yii\web\View */
use yii\helpers\Html;
$this->title = 'Hotel list';
$this->params['breadcrumbs'][] = $this->title;
?>
<?php foreach ($items as $item): ?>
<p> <?= $item-> name ?></p>
<p> <?= $item->address ?></p>
<p> <?= $item->description ?></p>
<?php endforeach; ?>
When I wrote var_dumps($items) under $items I can see the datas. However in the view It says Trying to get property 'name' of non-object. What did I wrong here please guide me. THanks for your time.
ArrayHelper::map()
Returns an array where, in your case, second argument passed is a key, the third is a value. So you need to access its elements as an array elements instead of class properties. Like:
<?php foreach ($items as $key => $value): ?>
<p> <?= $key ?></p>
<p> <?= $value ?></p>
<?php endforeach; ?>
More details here: https://www.yiiframework.com/doc/api/2.0/yii-helpers-basearrayhelper#map()-detail
But if you need to access data as class properties change the line in your controller:
$items = ArrayHelper::map(Hotel::find()->all(), 'id', 'name');
to:
$items = Hotel::find()->all();
$items = Hotel::find()->all();
I should not add Array Helper
Related
I created a method in a model of CI4 to query a search results. I need to paginate search results but the URL not provide results. I need to standard way for pagination in CI4.
Here is model method -
<?php
public function search($key)
{
$builder = $this->table('apps_common_all');
$builder->Like('name',$key,'after');
$query = $builder->paginate(51);
return $query;
}
?>
controller method is -
<?php
public function result()
{
$key = $this->request->getVar('s');
$apps = new AppsModel();
$data = [
'items' => $apps->search($key),
'pager' => $apps->pager,
];
return view('search/index',$data);
}
?>
Pagination code in view page
<?php if ($pager) :?>
<?php $pagi_path=getenv('pagi_path').'search_result'; ?>
<?php $pager->setPath($pagi_path); ?>
<?= $pager->links() ?>
<?php endif ?>
when pagination link clicked the url not provide results
http://myshahadat.com/demo/apkdownload/search_result?s=a&page=2
and my route is
<?php $routes->get('/search_result', 'Search::result'); ?>
I am coding a form to get user input and then pass that information to a controller and execute a function based on that, at this point I can not pass the data to the controller using POST method, I get empty vars.
So the Controller function display the view form correctly, I can type on the textboxes, after press submit button I get a setFlash custom message that the parameters are empty. I am using a model class with just two parameters.
a) This is the model:
<?php
namespace app\models;
use Yii;
use yii\base\Model;
class SendmailForm extends Model
{
public $template;
public $emtransport;
/**
* #return array the validation rules.
*/
public function rules()
{
return [
[['template', 'emtransport'], 'required'],
];
}
}
b) This is the view:
<?php
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use yii\captcha\Captcha;
$this->title = 'Send Mail';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-contact">
<h1><?= Html::encode($this->title) ?></h1>
<?php if (Yii::$app->session->hasFlash('sminfo')): ?>
<div class="alert alert-success">
<?= Yii::$app->session->getFlash('sminfo');?>
</div>
<?php else: ?>
<p>
SendMail Exercise. Please choose needed options bellow:
</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'sendmail-form']); ?>
<?= $form->field($model, 'template')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'emtransport') ?>
<div class="form-group">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'value'=>'one', 'name'=>'sendbtn']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
<?php endif; ?>
</div>
And this is the controller's function:
public function actionSendmail(){
$model = new SendmailForm();
if ($model->load(Yii::$app->request->post())) {
$template = Yii::$app->request->post('template');
$emailTransport = Yii::$app->request->post("emtransport");
if($emailTransport=="local"){
for($i=0;$i<=2;$i++){
$xclient = 'client' . $i;
\app\models\User::findByUsername($xclient)->sendMail($template, 'Welcome To XYZ Services', ['accountInfo' => 'www.mysite.com']);
}//end of for loop
Yii::$app->session->setFlash("sminfo", "Emails sent successfully to the Clients");
return $this->refresh();
}//end of second if loop
else{
Yii::$app->session->setFlash("sminfo", "Params could not be verified!. Contact Tech Support");
return $this->refresh();
}
}//end of post if loop
return $this->render('sendmail', [
'model' => $model,
]);
}
The idea is to get the values from the view, at this moment I am getting empty values-
Two parts below:
$template = Yii::$app->request->post('template');
$emailTransport = Yii::$app->request->post("emtransport");
Change the following:
$template = $model->template;
$emailTransport = $model->emtransport;
After editing
public function actionSendmail(){
$model = new SendmailForm();
if ($model->load(Yii::$app->request->post())) {
$template = $model->template;
$emailTransport = $model->emtransport;
if($emailTransport=="local"){
for($i=0;$i<=2;$i++){
$xclient = 'client' . $i;
\app\models\User::findByUsername($xclient)->sendMail($template, 'Welcome To XYZ Services', ['accountInfo' => 'www.mysite.com']);
}//end of for loop
Yii::$app->session->setFlash("sminfo", "Emails sent successfully to the Clients");
return $this->refresh();
}//end of second if loop
else{
Yii::$app->session->setFlash("sminfo", "Params could not be verified!. Contact Tech Support");
return $this->refresh();
}
}//end of post if loop
return $this->render('sendmail', [
'model' => $model,
]);
}
I did some changes to the Controller and now it works, those are them:
//at the beginning of the Controller:
use app\models\SendmailForm;
//two lines changed in the function:
$model->template = $_POST['SendmailForm']['template'];
$model->emtransport = $_POST['SendmailForm']['emtransport'];
That's all I needed. Best regards
So in my controller MenuController.php I have the following code:
class MenuController extends AppController {
public $helpers = array('Html', 'Form');
public function index() {
$this->set('menus', $this->Menu->find('all'));
$userSpecific = $this->Menu->find('all', array(
'conditions' => array('Menu.user_id' => '20')
));
}
}
and in my view, I am doing the following:
<?php foreach ($menus as $menu): ?>
<?php echo $menu['Menu']['id']; ?>
<?php echo $menu['Menu']['user_id']; ?>
<?php endforeach; ?>
update
To better understand this in my browser I changed my view to the following:
<?php foreach ($menus as $menu): ?>
<p>Menu id <?php echo $menu['Menu']['id']; ?> is for user: <?php echo $menu['Menu']['user_id']; ?></p>
<?php endforeach; ?>
end update
Now in the view, it is currently using the $this and returning all values from the database table, How do I change the view to use $userSpecific rather than $this I managed to get this far (making the $userSpecific part) by using the cookbook but I could only find the controller side and not the view side. I'm sorry if it's a bad question, just trying to learn.
You need to send the data to the view from the controller at the end of the index() function.
You can do it like this:
$this->set('userSpecific', $userSpecific);
or like this (my preferred way)
$this->set(compact('userSpecific');
Once you've done this, you can then modify your view to show the user specific fields as shown:
<?php foreach ($userSpecific as $menu): ?>
<?php echo $menu['Menu']['id']; ?>
<?php echo $menu['Menu']['user_id']; ?>
<?php endforeach; ?>
I'm facing validation problems integrating my custom module in zfcAdmin and BjyAuthorize.
My form class:
...
$formOptions = $this->settings->getFormSettings();
foreach ($formOptions as $field){
if (isset($field['field']))
$this->add($field['field']);
}
...
My filter class:
$formOptions = $this->settings->getFormSettings();
foreach ($formOptions as $filter){
if (isset($filter['filter']))
$this->add($filter['filter']);
}
...
Fields, filters and other options are retrieved from config file.
Basically everything works fine: form data can be added, edited or deleted from db.
Also after the zfcAdmin module installation no problem rose. Everything works fine using both 'site/mymodule' route and 'site/admin/mymodule' route: i can still add, edit and delete items from db.
Here the problem: I need some form elements (a Select in this particular case) editable/viewable only by administrator. (I can write a new controller/entity class 'ad hoc' for admin but i would like to use the same code for the whole site.)
I installed and configured bjyoungblood/BjyAuthorize module: it allowed me to display some form elements/fields only to admin but when i'm in edit mode a form validation error is displayed: "Value is required and can't be empty"
Here the code:
//view/mymodule/mymodule/update.phtml
<div id="page" style="margin-top: 50px;">
<?php if (isset($this->messages) && count($this->messages) > 0 ): ?>
<?php foreach ($this->messages as $msg): ?>
<div class="alert alert-<?php echo $this->escapeHtmlAttr($msg['type']); ?>">
<?php if (isset($msg['icon'])) echo '<i class="'.$this->escapeHtmlAttr($msg['icon']).'"></i> '; ?><?php echo $this->escapeHtml($msg['message']); ?>
</div>
<?php endforeach; ?>
<?php endif; ?>
<?php
$title = 'Edit Item';
$this->headTitle($title);
?>
<h1><?php echo $this->escapeHtml($title); ?></h1>
<?php
$form = $this->form;
$form->setAttribute('action', $this->url($this->route . 'mymodule/update', array('action' => 'update', 'id' => $this->id )));
$form->prepare();
$form->setAttribute('method', 'post');
$input = $form->getInputFilter();
?>
<?php echo $this->form()->openTag($form) ?>
<dl class="zend_form">
<?php foreach ($form as $element): ?>
<?php
//CHECK USER PRIVILEDGES
$elName = $element->getName();
$elResource = isset($this->form_options[$elName]['auth']) ? $this->form_options[$elName]['auth']['resource'] : "userresource";
$elPrivilege = isset($this->form_options[$elName]['auth']) ? $this->form_options[$elName]['auth']['privilege'] : "view";
//SHOW THE ELEMENT IF ALLOWED
if($this->isAllowed($elResource, $elPrivilege)):
?>
<?php if ($element->getLabel() != null): ?>
<dt><?php echo $this->formLabel($element) ?></dt>
<?php endif ?>
<?php if ($element instanceof Zend\Form\Element\Button): ?>
<dd><?php echo $this->formButton($element) ?></dd>
<?php elseif ($element instanceof Zend\Form\Element\Select): ?>
<dd><?php echo $this->formSelect($element) . $this->formElementErrors($element) ?></dd>
<?php else: ?>
<dd><?php echo $this->formInput($element) . $this->formElementErrors($element) ?></dd>
<?php endif ?>
<?php else: ?>
<?php
?>
<?php endif ?>
<?php endforeach ?>
</dl>
<?php echo $this->form()->closeTag() ?>
</div>
<div class="clear-both"></div>
My controller action
//controller
public function updateAction(){
$messages = array();
$id = (int)$this->getEvent()->getRouteMatch()->getParam('id');
$form = $this->getServiceLocator()->get('FormItemService');
$itemMapper = $this->getItemMapper();
$item = $itemMapper->findById($id);
$form->bind($item);
$request = $this->getRequest();
if($request->isPost()){
$form->setData($request->getPost());
if ($form->isValid()) {
die('c');//never here
$service = $this->getServiceLocator()->get('mymodule\Service\Item');
if ( $service->save($form->getData()) )
{
$messages[] = array(
'type' => 'success',
'icon' => 'icon-ok-sign',
'message' => 'Your profile has been updated successfully!',
);
}
else
{
$messages[] = array(
'type' => 'error',
'icon' => 'icon-remove-sign',
'message' => 'Profile update failed! See error messages below for more details.',
);
}
}else{
var_dump($form->getMessages());//Value is required and can't be empty
}
}
return array(
'messages' => $messages,
'form' => $form,
'id' => $id,
'form_options' => $this->getServiceLocator()->get('mymodule_module_options')->getFormSettings(),
'route' => $this->checkRoute($this->getEvent()->getRouteMatch()->getmatchedRouteName())
);
}
If user is not allowed to view the resource, the element is not echoed. So $request->getPost() has no value for that form element and an error is returned by isValid().
Has anyone solved a similar problem or can anyone point me to the right direction?
Thanks
The problem is that you don't do any security check in your FormFilter class, where you define your required fields.
The $form->isValid() function checks the posted data against those filter elements. So it's not enough to prevent the 'echo field' in your view, you still need to apply the security check to the filter element.
One other approach would be to make two forms one for the front end and one for the admin. Since the one for the admin will have the same fields plus one extra select field you can make the admin form extends the front end one. E.g.
class myForm
{
public function __construct(...)
{
// add fields and set validators
}
}
and the admin form could be:
class MyAdminForm extends myForm
{
public function __construct(...)
{
parent::__construct(...);
// add the extra field and extra validator
}
}
In that way even if you edit the front end form (or validators) the back end will always be up to date.
Hope this helps :),
Stoyan
Issue/Question: I'm using CodeIgniter to build an event calendar, and I have included a sharing option. This option works at a base level, but only displays the users' ID (primary key) in an <ul>. This isn't ideal, and I would like to show the users' first and last names in the <ul> instead. I thought creating an associative array would work, but I'm receiving funky results. The first and last name echo out as "Array Array" when the page loads, and the URL id comes up as "Array" when you select the "Array Array" link. I'm wondering what is wrong in my logic.
Funky link generated in view:
Array Array
Funky URL that is linked to "Array Array":
http://example.com/user/shared/view/Array
Modified Controller:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Shared extends Common_Auth_Controller {
private $end_user;
public function __construct()
{
parent::__construct();
$this->end_user = $this->ion_auth->user()->row();
$data['end_user'] = $this->end_user;
$this->load->vars($data);
$this->load->model('events_model', 'events');
}
public function index()
{
$title['title'] = 'Shared';
$this->load->model('shared_model','shared');
$data['sharers'][] = array(
'shared_owner_id' => $this->shared->get($this->end_user->id),
'owner_first_name' => $this->shared->get($this->end_user->first_name),
'owner_last_name' => $this->shared->get($this->end_user->last_name),
);
$this->load->view('public/head_view', $title);
$this->load->view('user/header_view');
$this->load->view('user/shared_view', $data);
$this->load->view('user/footer_view');
}
Modified View:
<div class="hide-on-phones">
<ul>
<?php foreach($sharers as $key => $value): ?>
<li><?php echo $value['owner_first_name']." ".$value['owner_last_name'] ?></li>
<?php endforeach; ?>
</ul>
</div>
Model:
class Shared_model extends crud_model {
public function __construct()
{
parent::__construct();
$this->pk = 'id';
$this->table_name = 'shared';
}
public function get($shared_to_user_id)
{
$this->db->where('shared_to_id', $shared_to_user_id);
$ids = parent::get_all();
$users = array();
foreach ($ids as $id)
{
$users[] = $id->owner_id;
}
return $users;
}
}
Thank you so much for your help, and let me know if there is any more information that may be required. Below are the original view and controllers that work, but are not preferable.
Original Controller:
public function index()
{
$title['title'] = 'Shared';
$this->load->model('shared_model','shared');
$data['sharers'] = $this->shared->get($this->end_user->id);
$this->load->view('user/head_view', $title);
$this->load->view('user/header_view');
$this->load->view('user/navigation_view');
$this->load->view('user/shared_view', $data);
$this->load->view('user/footer_view');
}
Original View:
<?php foreach($sharers as $s): ?>
<li><?php echo $s ?></li>
<?php endforeach; ?>
Disclaimer: I'm new to web development, and I suck at associative arrays (apparently).
Your $data['sharers'] array doesn't have arrays as $values. Therefore, the way you are calling the $value[]'s in your foreach aren't working. You have no reason for calling the foreach at this point.
<div class="hide-on-phones">
<ul>
<li><a href="<?=base_url('user/shared/view/'.$sharers['shared_pk_id'])?>">
<?=$sharers['first_name'] . ' ' . $sharers['last_name']?>
</a>
</li>
</ul>
</div>
I expect you will later on fill an array with the data, in which case you can fill it as
$data['sharers'][] = array(
'shared_pk' => $this->shared->get($this->end_user->id),
'first_name' => $this->events->get($this->end_user->first_name),
'last_name' => $this->events->get($this->end_user->last_name)
);
Which, in turn can be looped using
<div class="hide-on-phones">
<ul>
<? foreach($sharers as $sharer): ?>
<li>
<a href="<?=base_url('user/shared/view/' . $sharer['shared_pk'])?>">
<?=$sharer['first_name'] . ' ' . $sharer['last_name']?>
</a>
</li>
<? endforeach; ?>
</ul>
</div>
I've figured it out. I needed to create an associative array in my model; not my controller. Thanks to everyone for your help!
Model:
class Shares_model extends crud_model {
public function __construct()
{
parent::__construct();
$this->pk = 'id';
$this->table_name = 'shares';
}
public function get($shared_to_user_id)
{
$this->db->where('shared_to_id', $shared_to_user_id);
$ids = parent::get_all();
$users = array();
foreach ($ids as $id)
{
$users[$id->owner_id]['owner_id'] = $id->owner_id;
$users[$id->owner_id]['owner_first_name'] = $id->owner_first_name;
$users[$id->owner_id]['owner_last_name'] = $id->owner_last_name;
}
return $users;
}
}
View:
<ul>
<?php foreach($sharers as $s): ?>
<li><?php echo $s['owner_first_name']." ".$s['owner_last_name'] ?></li>
<?php endforeach; ?>
</ul>
Controller:
public function index()
{
$title['title'] = 'Shared';
$this->load->model('shares_model','shares');
$data['sharers'] = $this->shares->get($this->end_user->id);
$this->load->view('public/head_view', $title);
$this->load->view('user/header_view');
$this->load->view('user/shared_view', $data);
$this->load->view('user/footer_view');
}
If we take your $data['sharers'] array and put in values for the php, then we would get something like this:
$data['sharers'] = array(
0 => array(
'id' => 1234,
'first_name' => 'John',
'last_name' => 'Doe'
),
1 => array(
'id' => 1235,
'first_name' => 'Jane',
'last_name' => 'Doe'
)
);
So, when you loop through this in your view, you need to access these correctly:
foreach($sharers as $key => $value):
// at this point, in the first iteration of the loop
// $key is 'id', or 'first_name', or 'last_name'
// and $value is 1234, or 'John', or 'Doe'
endforeach;
So, to loop through the sharers a bit easier, you just need to update your foreach a bit. At this point, change your view to this:
<div class="hide-on-phones">
<ul>
<?php foreach($sharers as $sharer): ?>
<li>
<a href="<?php echo base_url('user/shared/view/'.$sharer['shared_pk_id']) ?>">
<?php echo $sharer['first_name']. " " .$sharer['last_name'] ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>