I'm trying link the form I created in yii, and make it to go to another page. However since I'm new to yii, I'm confused if it's calling the controller, model or view, plus I dont have a clue where the rendering of the new page should be placed.
I've just taken over someone's work and I'm still studying the yii framework itself.
The code for the form is:
<?php $form=$this->beginWidget('CActiveForm', array('id'=>'apply-form','action' =>
'/site/apply','enableAjaxValidation'=>false,'htmlOptions' => array('enctype' => 'multipart/form-data'),)); ?>
and for the site controller its
public function actionApply()
{
$model = new ApplyForm;
if(isset($_POST['ApplyForm']))
{
$model->attributes=$_POST['ApplyForm'];
$stringsubject ="Application for Crunch Marketing-".$_POST['ApplyForm']['fieldName'];
$model->subject = $stringsubject;
if($model->validate())
{
$mailer = new EmailSender();
$success = $mailer->send($model, 'test#crunch.com.ph');
}
}
$this->render('index',array(
'contactModel' => new ContactForm,
'applyModel' => $model,
));
}
I dont know how the flow actually works. I'm used to the standard form action call, so I'm really confused.
The answer is very broad.
To have idea about fundamental things in yii this is good article I came by through:
http://www.larryullman.com/2009/10/31/getting-started-with-the-yii-framework/
Read the whole series.
May it helps to clear the flow.
Firts you need read this:
http://www.yiiframework.com/doc/guide/1.1/en/basics.mvc and all fundamentals
Your form is send '/site/apply' , site is the controller and apply is a controller action, this action render the view site/index
Related
i'm from codeIgniter , but for an internship I have to debug an ongoing website using cakePHP.
I'm familiar with mvc but currently stuck and unable to find any solution even after searching.
What I want is to be able to call a function in a controller (easy task with codeIgniter) ,but during the debug I noticed that the controller was called, but not the function:
<?php
App::uses('AppController', 'Controller');
class FournisseursController extends AppController { //debug stop here
public $helpers = array('Html', 'Form');
public function index() {
$this->set('Personnes', $this->Fournisseur->find('all'));
}
public function addFournisseur() {
//contain some code , but not usefull for this problem
}
}
}
?>
after the 2 first line , the associated view is displayed (it's a weird concept to always have a view displayed, but I guess cake php work this way).
and debug dont even start on the targeted function.
I call it from a view:
<form action="../../Fournisseurs/addFournisseur" method="post">
<input type="submit">
</form>
I know it's not really good to call a controller from view , but in that case I need the user to enter some data to send it in a database, I dont know any other way.
I already read the doc concerning controller and it didnt help.
One last thing , if I change the name of the function in the controller , the controller will not be called : an error message explain the the method dont exist (so for me the controller know I want to call the function, because the controller need it to run).
it's been a day since i'm stuck on this and i'm pretty sure it's a stupid mistake.
thanks for reading this even if you dont answer , and sorry if I made any english mistake, it's my first post and i'm not a native speaker.
I was only relying on Xdebug ,despite the breakpoint it was not stopping in the function ,so I thought it was not called (the function and the code inside it), but with the help of the debug($data) function the breakpoint worked and I was able to keep debuging in the function.
I dont know why Xdebug acted this way ,but I will not rely only on it now.
thanks to everyone who helped, I can keep going now!
You can also use Form helper like below, where you can define the contoller and action name:
<?php echo $this->Form->create('Fournisseur', array('url' => array('controller' => 'Fournisseurs', 'action' => 'addFournisseur'))); ?>
// Form elements
<?php echo $this->Form->end(); ?>
In CakePHP, I am trying to create a autocomplete function from a textbox, using this tutorial: http://bakery.cakephp.org/articles/matt_1/2011/08/07/yet_another_jquery_autocomplete_helper_2
I keep getting a
Error: AutoCompleteHelper could not be found.
Undefined index: autoCompleteText
I am unsure how to fix this as I have tried relocating the files and still the same error.
I create the below files and copy the code from the tutorial,
create the auto_complete.php in the view/helpers directory,
and create webroot/js/views/helpers/auto_complete.js.
controller - Tests
function auto_complete
class TestsController extends AppController {
public $helpers = array('Html', 'Form', 'Session','Js','AutoComplete');
public function auto_complete() {
$this->loadModel('Tutor');
debug( $this->params);
$terms = $this->Tutor->find('all', array(
'conditions' => array(
'Tutor.first_name LIKE' => $this->params['url']['autoCompleteText'].'%'
),
'fields' => array('Tutor.first_name'),
'limit' => 3,
'recursive'=>-1,
));
$terms = Set::Extract($terms,'{n}.Tutor.first_name');
$this->set('terms', $terms);
$this->layout = '';
}
view
auto_complete.ctp
<?php
echo $this->AutoComplete->input(
'Tutor.first_name',
array(
'autoCompleteUrl'=>$this->Html->url(
array(
'controller'=>'tests',
'action'=>'auto_complete',
)
),
'autoCompleteRequestItem'=>'autoCompleteText',
)
);
if(isset($terms)) {
echo $this->Js->object($terms);
}
echo $this->Form->create('');
echo $this->Form->input('type', array('label' => 'Choose' ));
echo $this->Form->end('send');
?>
I had a good look around previous posts and I really couldnt solve the problem.
Cakephp form input with autocomplete
The tutorial you're looking at is for CakePHP 1.x (it's from August 2011, Cake 2 came out in October '11), but you're running Cake 2.5. The naming standards have changed between 1.x and 2.x, so Cake can't see your helper.
First: Your main problem is that you're naming your helper auto_complete.php when it should be AutoCompleteHelper.php.
Second, you are placing it in the wrong directory. In Cake 1.x, helpers lived under /view/helpers/. In 2.x, they live under /View/Helper/.
Third, regarding the undefined index error, you need to understand how this helper works in the first place, and why you're implementing it incorrectly.
The controller action auto_complete should not have a view. It's just a data source. When you use the helper, it loads the Javascript, which does its magic by polling /auto_complete?autoCompleteText=stringgoeshere.
You might notice that you removed $this->layout = 'ajax'; from the controller action, probably because your toolbars weren't rendering. They weren't supposed to. It's just a datasource, it NEEDS the ajax layout, and there should be no view on that action.
Because you were trying to put a form on your auto_complete action and not on another action, the helper was looking for the query parameter autoCompleteText, not finding it, and displaying an error.
You can solve this by changing the auto_complete action back as close as possible to how it was in the example, deleting auto_complete.ctp, and by trying to use the helper in the correct view, like add.ctp.
Fourth: You shouldn't be using jsHelper anymore. It's been deprecated in 2.5 and is going to disappear in the future. Basically, the tutorial is obsolete.
However, it's really easy to just replace $this->set('terms', $terms); with return json_encode($terms) and write your own piece of JS to make an AJAX call. I suggest incorporating Typeahead.js.
Finally: You should consult the 1.x -> 2.x migration guide, and as well, once you get your helper running you've got some other typos in your code that will break it anyway- "Ttuor.first_name", for example. Good luck!
I've inherited a website built using Codeigniter (v2.1.4). The client has asked for a change, and I'm not sure of the best way to achieve it.
I have the following method in the Main controller that powers a new vans page.
public function new_vans($slug = null){
$this->load->view('inc/header_view');
if($slug === NULL){
//If no slug is provided, show all new vans
$this->load->view('new_vans_view');
}else{
//If there is a slug, just show the selected van, or redirect if nothing returned
$data['new_van'] = $this->Database->getSingle('new_vans', array('slug' => $slug));
if(!empty($data['new_van'])){
$this->load->view('new_van_details_view',$data);
}else{
redirect('/new-vans');
}
}
$this->load->view('inc/footer_view');
}
The client has asked for a contact form to be added to a couple of pages including this one, and my question is, should I create a new method that just handles the contact form submissions? If so, how would I handle sending validation errors back to the page? The contact forms will all have the same fields, so I would guess creating a new method is the way to go?
Partial Views(forms)
Partial views are good for forms, they can be re-used
like your client has requested.
Returning views as data
There is a third optional parameter lets you change the behavior
of the function so that it returns data as a
string rather than sending it to your browser.
This can be useful if you want to process the data in some way.
If you set the parameter to true (boolean) it will return data.
The default behavior is false, which sends it to your browser.
Remember to assign it to a variable if you want the data returned:
$string = $this->load->view('myfile', '', true);
Master layouts
To create a Master layout so you can wrap your views
create a new file inside your views directory
views/master/layout.php
<body>
<?php $this->load->view($view); ?>
</body>
Controller
class someController extends CI_Controller
{
public function __construct()
{
parent::__construct();
$this->template = 'master/layout';
}
public function index()
{
return $this->load->view($this->template, array(
'view' => 'somecontrollerview',
'contact_form' => $this->load->view('partials/forms/contact', array(), true)
));
}
}
somecontrollerview
Echo out the contact form(string)
<?php echo $contact_form; ?>
Contact Controller
Create a new Controller to handle your form validation
The client has asked for a contact form to be added to a couple of pages including this one, and my question is, should I create a new method that just handles the contact form submissions?
create a new controller and new methods
If so, how would I handle sending validation errors back to the page?
look through the codeigniter documentation for form validation. basically if they have an error you are going to show them a view with the form again. it does not matter which page they came "from".
The contact forms will all have the same fields, so I would guess creating a new method is the way to go?
you need to validate the form fields, hopefully capture the contact info to a database, send an email confirmation to the customer, and send an email to the sales person unless its being done directly from the database, and then show a view with a thank you.
each one of those steps is a separate method.
optionally you can show the email address on the thank you page saying 'we have sent you a copy to the email address: something#gmail.com -- that way if the customer messed up the email address they can go back and correct it.
This is a best practice question and not a specific issue.
I'm fairly new to the MVC approach and Yii, and have developed on an app for a while now. I keep seeing talks on best practice and what to put in which file (controller, model, view, helper etc.) however i have not yet found anything specific in terms of examples.
I currently have calls like: Model::function() in my view files as well as checks like $var = app()->request->getParam(value, false);
I have calls in my controller file like Model::function() and Model::model()->scope1()->scope2()->findAll() I also think my controller files are getting a bit thick, but not sure how and where to put some of the bloat, i have been reading about the DRY and i think i'm not exactly DRY'ing my code so to speak.
Could you give me a more clearer picture about what goes where, and suggestions or reasons why :)
Appreciate any advice, thanks in advance.
here's an example call in a viewfile
<?php
$this->pageTitle = 'Edit Action';
$this->subTitle = '<i>for</i> <b>' . Vendors::getName($_GET['vendor']) . '</b>';
?>
<div class="wrapper">
<?php echo $this->renderPartial('_form', array('model' => $model)); ?>
</div>
The getName is my function in the model, is this a good way to call a function in a view?
Another example view file:
<div class="wrapper">
<?php
if($this->action->id != 'create') {
$this->pageTitle = "New Media Contact";
echo $this->renderPartial('_form', array('model'=>$model));
} else {
$this->pageTitle = "New Vendor";
echo $this->renderPartial('_form', array('model'=>$model));
}
?>
</div>
$model is set in the controller with type...
Same question... could this be done.. cleaner..? better in terms of MVC and reusability/DRY?
EDIT
After reading some of the responses here, esp. #Simone I refactored my code, and wanted to share what it looks like now...
public function actionCreate() {
$model = new Vendors;
// Get and Set request params
$model->type = app()->request->getParam('type', Vendors::VENDOR_TYPE);
$vendorsForm = app()->request->getPost('Vendors', false);
// Uncomment the following line if AJAX validation is needed
$this->performAjaxValidation($model);
if ($vendorsForm) {
$model->attributes = $vendorsForm;
if ($model->save())
$this->redirect(array('/crm/vendors', array('type' => $model->type)));
}
$model->categories = Categories::getAllParents($model->type);
$this->pageTitle = 'New ' . Lookup::item('VendorType', $model->type);
$this->render('create', array(
'model' => $model,
));
}
and the view create.php
<div class="wrapper">
<?php echo $this->renderPartial('_form', array('model'=>$model));?>
Thanks for all respnses
I am not too familiar with the Yii framework but can offer a few suggestions on a few specific things you mentioned:
Don't get too caught up with 'best practices' as like all design patterns MVC can be implemented and in certain cases interpreted in many different ways by different developers. So what does this mean? it means read up on MVC as much as you can, then simply just have a go :o) You will soon find out what slots where and why when you come up with a problem (which is normally along the lines of 'where does this belong, the controller or model?...'.
In terms of what goes where, you can google / search stackoverflow or read in countless books many explinations of what should do what and go where, but from the code snippet you provided I would suggest:
View files: (Unless this is a Yii specific thing) in my opinion your view files are a bit dirty. You are talking to the model directly (which is in fact the classical approach of MVC rather than some PHP app's adopting the 'controller is the only one allowed to speak to the model' method) but it appears your view is trying to get request data directly and for me this should not be anywhere near the view. The controller should be dealing with the request, using a model for validation and then passing the output into the view.
Model: This seems OK from the small snippet, but in general one important thing to remember is that the model != database (despite some people's suggestion that it is).
Controller: Again seems fine from your snippet, but to address your bloat in your controller, without seeing one of your controllers it would be hard to offer a suggestion. One thing that is always worth considering is the use of Services. Basically a service can be used to greatly simplify your controller by encapsulating a lot of repetitive / complicated model stuff. So instead of calling separate validation and persistence models within your controller, you just instantiate a service class, and it could just be a case of calling one method (which often returns a bool to indicate to your controller the success or failure of the operation) and then your controller just has to deal with what it does best (and should only do) the app's flow (i.e. redirect to another page, show error, etc).
I'll show you an'example to refactor your code. This is you code
<div class="wrapper">
<?php
if($this->action->id != 'create') {
$this->pageTitle = "New Media Contact";
echo $this->renderPartial('_form', array('model'=>$model));
} else {
$this->pageTitle = "New Vendor";
echo $this->renderPartial('_form', array('model'=>$model));
}
?>
</div>
First question is: why write two time the same line with renderPartial? First refactoring:
<div class="wrapper">
<?php
if($this->action->id != 'create') {
$this->pageTitle = "New Media Contact";
} else {
$this->pageTitle = "New Vendor";
}
echo $this->renderPartial('_form', array('model'=>$model));
?>
</div>
And now second step:
<?php $this->pageTitle = $this->action->id != 'create' ? "New Media Contact" "New Vendor"; ?>
<div class="wrapper">
<?php echo $this->renderPartial('_form', array('model'=>$model)); ?>
</div>
FOR ME is more readable. I thing there are a lot of best practice. But can become a bad practice used in bad context. So... Is really useful rewrite code? For me yes! Because my goal is maintainability of code. Easy to read, easy to manage. But you need to find your standard or your team standard. Also, I prefer move any kind of logic in controller. For example I can set a default pageTitle in controller and redefine It in actionCreate method:
class SomeController extends CController
{
public $pageTitle = "New Vendor";
function actionCreate ()
{
$this->setPageTitle("New Media Contact")
$this->render('view');
}
}
And my viewfile will become just:
<div class="wrapper">
<?php echo $this->renderPartial('_form', array('model'=>$model)); ?>
</div>
I think we have to understand the responsibility of things: view is just a view.
Simply think of a view as a component that only display data. It shouldn't do database calls, interact with a model, create new variables (or very rarely), etc. If you want to do a check, or create an HTML block using some data, etc. use helpers for that purpose.
The data a view will display will come from a controller.
The controller is the maestro who'll do most of the work in your app: it will answer requests, ask the model for data if needed, pass the data to a view and render it, etc.
In your first example, simply save Vendors::getName($_GET['vendor']) in a variable, in your controller, and then pass it to the view.
Also, if you don't need all model's data, don't pass the whole object.
Regarding your second snippet, first of all you can move the echos out of the if statement because they are the same.
A good thing would be to do the check if ($this->action->id != 'create') in your controller, and give your view a simple boolean:
if ($this->action->id != 'create') { // not sure if $this->action->id would remain the same, I don't know Yii
$media = true;
// or
// $page = 'media';
} else {
$media = false;
// or
// $page = 'vendor';
}
And the render the partial depending on the values returned by the controller.
In my opinion there is no "best practice". As long as you do not work in a team or want to release your script as open source, where dozens of people have to work with it, use the framework however you like and need it. And even if you work with others on the code there are no "god given" rules for that.
There are much more important things that matter than the question if you are "really allowed" to use a static function inside your view.
I'm trying to make some ajax-functionality in my web application, but I cannot get all puzzle pieces to fit:
I want to add a link that, when clicked upon, will open a new input (text) field that can be filled by the user. In the back-end, I want to do some administration that the link is clicked.
I want to do according to the Zend Framework principles, with using the ajaxLink() method. Can anyone have an example for me? I've read the official documentation (ZendX_JQuery) but it doesn't fully help me.
My front-end (view) code looks like this;
<?= $this->ajaxLink("Subscribe", $this->url(array('controller' => 'mycontroller', 'action' => 'action1', 'id' => $event['id'])),
array("beforeSend" => "hide",
"update" => "#pb_" . $event['id'],
'noscript' => false,
'method' => 'POST')); ?>
My back-end code looks like this.
public function action1Action()
{
if( !$this->loggedIn || ! $this->athlete) {
$this->_redirect('index');
}
if(! $this->_request->isXmlHttpRequest())
{
//The request was NOT made with JS XmlHttpRequest
die;
}
// Do some administration
// (removed to make this easier in this example)
$pb = new Zend_Form_Element_Text('PB');
$pb->setLabel('PB:')
->addValidator('StringLength', false, array(0,20))
->setRequired(false);
$renderText = $pb->render();
return $renderText;
}
I keep getting errors back that the given method wants to look-up a action1.phtml view script. I'm also not sure if what I try to do with the generation of the form input element works in this way.
I found some of the answer in this question, but it's not that elegant (requires an extra parameter in the link and you need another controller) which I don't like.
You need to turn off the ViewRenderer for this particular action. ZF by default enables an Action Helper called ViewRenderer which assigns a conventionally named view script (in your case, action1.phtml) to a particular action method. Since you're only trying to return a small snippet of text, rather than a full site view, full view rendering isn't necessary. Fortunately, this is easy.
public function action1Action(){
$this->_helper->viewRenderer->setNoRender();
// the rest of your code
}
The full docs are here:
http://framework.zend.com/manual/en/zend.controller.actionhelpers.html#zend.controller.actionhelpers.viewrenderer
There's nothing to it. All you have to do is point it to where your content is coming from. In your view:
<?= $this->ajaxLink("Example 1","/controller/action1",
array('update' => '#content',
'noscript' => false,
'method' => 'POST')); ?>
In your controller:
echo 'Some Content';
Read this:
http://www.mikaelkael.fr/IMG/pdf/ZendX_Framework_1.7.x_EN.pdf