I have a small form, where user's can Subscribe to my newsletter.
How can i pass the email address from my Layout to my Controller?
My Layout name is Footer.phtml, here's the code:
<div id="subscribe">
<form name="newsletterRegister" method="post" action="">
<span>Subscribe to the Newsletter</span>
<input class="subscribeNewsletter" name="email" type="text">
<input id="subscribe_ok" type="image" src="/www/assets/newImages/footer/Ok.png" value="">
</form>
</div>
I have a controller called NewsletterController.php
I'm kinda lost with Zend Framework, can anyone help me figuring out what i have to do??
Well change this
<form name="newsletterRegister" method="post" action="">
To this
<form name="newsletterRegister" method="post" action="NewsletterController/YOURACTION">
And in your controller just get the data like this
$request = $this->getRequest();
$request->getPost()
If the action of your form is empty, it will post to itself.
But maybe you dont want to check on every page if the newsletter is send.
Try using a Controller Plugin, check the request object for the input field, name it unique like email_newsletter, if is not empty, do your logic.
File: application/plugins/Newsletter.php
class Application_Plugin_Newsletter extends Zend_Controller_Plugin_Abstract {
//before dispatching starts
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$email = $request->getParam('email_newsletter',NULL);
if(!is_null($mail)) {
//check if is valid
if(Zend_Validate::is($email,'')) {
//do your logic
}
else {
//set some error messages
//maybe use helper flashMessenger
}
}
}
}
File: Bootrap.php
protected function _initPlugins() {
$this->bootstrap('frontController');
//Get FrontController Instance
$frontController = $this->getResource('frontController');
$frontController->registerPlugin(new Application_Plugin_Newsletter());
return $frontController;
}
OR
Set a form action like '/newsletter/subscribe'.
Then in controller 'newsletter' action 'subscribe' check the form and redirect to the sending page.
Maybe you should store sth like a last page visited to the session, or add a hidden input to that newsletter form, representing the current page you want to redirect to after the newsletter subscription is done.
Related
I create a hook allowing the user to send a csv file.
I want to get the data (the file) that the user sends via a form (present in views/templates/hook), to get it in controller/front/files.php, and insert it in my database, anyone have an idea?
my hook in mymodule.php
public function hookDisplayLeftColumnProduct($params)
{
$this->context->smarty->assign([
'files' => Tools::getValue('files')
]);
return $this->display(__FILE__, 'mymodule.tpl');
}
views/templates/hook/mymodule.tpl
<div id="mymodule_block_home">
<form method="POST">
<label for="files">Envoyer un fichier CSV</label>
<input type="file" name="files" id="files">
<button>Envoyer</button>
</form>
</div>
my front controller who's not good I guess
class MyModuleFilesFrontController extends ModuleFrontController
{
public function initContent()
{
parent::initContent();
$files = Tools::getValue('files');
$this->setTemplate('module:mymodule/views/templates/front/files.tpl');
}
}
Thank you for your help
It is not a PrestaShop-specific problem. You might want to read about uploading files in PHP there:
https://www.tutorialspoint.com/php/php_file_uploading.htm
A few hints:
check if there is something to upload, always
make sure to validate user input, always
One more thing. I see that you hook your module into the product page. You could have the logic of uploading a file directly in your hook. You don't need an extra controller for that.
You could do something like:
public function hookDisplayLeftColumnProduct($params)
{
if (Tools::isSubmit('yourSubmitButtonName') {
// here's the logic of uploading the file
}
// the rest of the code
}
I have a form in a tpl file:
<form action="{$link->getModuleLink('virtual_pos', 'validation', [], true)|escape:'html'}" method="post">
...
</form>
On submit I would like to get all the variables from the form and pass them to the controller 'validation'.
I don't wanna use any JS. It is a payment module for a store.
How can I do this?
I have found a solution in another thread.
When the link to the controller is created you can fill the variables that you need in the empty array parameter:
<form action="{$link->getModuleLink('virtual_pos', 'validation', ['id'=>$cart_id], true)|escape:'html'}" method="post">
Then in the controller you can get the data with the super global
$id_from_form_submit = $GET['id'];
If you know any other option please let me know.
In your module create a file controllers/front/validation.php.
There you need a class:
class virtual_posValidationModuleFrontController extends ModuleFrontController
{
public function postProcess()
{
/* where you get the values and validate the order */
}
public function initContent()
{
parent::initContent();
/* where you set data for a last page order confirmation */
}
}
Have you created this already?
I have two forms on a page both submits the data via POST method. I want to handle both requests on the same url i.e /home and use different controllers and methods for both forms. Below are the two routes.
Route::post('home' ,'FacebookControllers\PostsController#save');
Route::post('home' , 'FacebookControllers\MessageController#storeMessage');
In PostsController#save I am checking
if(isset($_POST['submitPost']) && $_SERVER['REQUEST_METHOD']=='POST'){
//do something
}
and in MessageController#storeMessage I am doing the same for other form
if(isset($_POST['sendMessage']) && $_SERVER['REQUEST_METHOD']=='POST'){
return "got it";
}
The problem is that only second route works. I don't if I am doing right or wrong. Please lead me to the right direction.
Route::post('home' ,'FacebookControllers\PostsController#save');
Route::post('home' , 'FacebookControllers\MessageController#storeMessage');
won't work - how should laravel determine where to post to? The way I would go is to create two jobs and one route, then check for the value in Request and dispatch the correct job.
First, create two job classes with
php artisan make:job FacebookSave
php artisan make:job FacebookStoreMessage
The generated file will look much like this:
<?php
namespace App\Jobs;
use App\Jobs\Job;
use Illuminate\Contracts\Bus\SelfHandling;
class FacebookSaveMessage extends Job implements SelfHandling
{
/**
* Create a new job instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
//
}
}
In the job's handle() method you can do what you wanted to do in your Controller.
Now the route, let's do
Route::post('home' ,'FacebookControllers\PostsController#findAction');
and according to this in your PostsController, add a method (I called it findAction) like this:
public function findAction(\Illuminate\Http\Request $request) {
if ($request->has('submitPost')) {
return $this->dispatch(new \App\Jobs\FacebookSave($request));
} else if ($request->has('storeMessage')) {
return $this->dispatch(new \App\Jobs\FacebookStoreMessage($request));
}
return 'no action found';
}
This way the correct action will be performed depending on the submitted value.
Change the job's constructor to something like:
public function __construct($data)
{
$this->data = $data;
}
And you can access the submitted values from the forms you have submitted inside the job's handle() method with $this->data
If the purpose is only to maintain the URL that appears in the browser, you may apply a trick in which you submit your post request to different ROUTES that are specifically exist for processing purpose and then redirect back to the same URL.
For example:
Route::post('home' ,'FacebookControllers\PostsController#save');
Route::post('message' , 'FacebookControllers\MessageController#storeMessage');
Then in your view , you maybe have two diffrent forms in the same view:
<!-- the first form -->
<form action="{{url('home')}}" method="post">
Enter your post:
<input type="text" name="post" />
<button type="submit" >Save</button>
</form>
<!-- the second form -->
<form action="{{url('message')}}" method="post">
Enter your post:
<input type="text" name="post" />
<button type="submit" >Save</button>
</form>
Now in your controller, in the both actions do something like :
public function save(Request $request)
{
// do stuff
$obj->save()
return redirect('home')->with('status' , 'you have saved your post')
}
public function storeMessage(Request $request)
{
// do stuff
$obj->save()
return redirect('home')->with('status' , 'your message has been saved')
}
By doing so, the URL will remain same for the user, after the process is done the user will be redirected back to the same URL with the status.
May be this is not a good coding practice, but it solve the problem by maintaining the same URL while having multiple posts to the same controller in the same view.
The most important point here is that you have to strictly prevent an error during the process by using conditions and redirect to the same URL in case of any problem, otherwise the action will try to show the user the tricky ROUTE (yoursite.com/message) for any error.
I want to create custom permalinks on CodeIgniter, actually i bought the script but the developer left that project due to some indifference. so now the problem is i have no idea how to change permalinks on that script. The main permalinks issue is when i search anything on searchbar i get this url:
domain.com/?s=xxxxx%20yyyyy
instead of that i want this url structure:
domain.com/search/xxxxxx-yyyyy/
application/config/routes.php
$route['default_controller'] = "music";
$route['404_override'] = '';
$route['search/(:any)'] = "music/index/$0/$1/$2";
$route['search/music/(:any)'] = "music/$1";
I guess what you are asking for is not possible (directly).
Assuming your form to be,
<form action="" method="GET">
<input type="text" name="s" value="" placeholder="Search music..." />
</form>
And since the method is GET the default functionality says to add the parameter in the URL as query string.
As the specifications (RFC1866, page 46; HTML 4.x section 17.13.3) state:
If the method is "get" and the action is an HTTP URI, the user agent takes the value of action, appends a `?' to it, then appends the form data set, encoded using the "application/x-www-form-urlencoded" content type.
So, basically what you can do here is apply a hack to this. Redirect the user to the required URL when the search is applied. Here's how you can go,
Controller (controllers/music.php)
<?php
class Music extends CI_Controller
{
public function __construct()
{
parent::__construct();
$this->load->model('xyz_model');
}
public function index()
{
if($this->input->get('s'))
{
$s = $this->input->get('s');
redirect('/search/'$s);
}
$this->load->view('home.php');
}
public function search()
{
$s = $this->uri->segment(2);
/*
Now you got your search parameter.
Search in your models and display the results.
*/
$data['search_results'] = $this->xyz_model->get_search($s);
$this->load->view('search_results.php', $data);
}
}
I have a html form that has this markup.
<form id="login-form" action="/post/login">
<input name="username" type="text">
<input name="password" type="password">
</form>
I want to be able to assert this form action.
I try with this inside the test method, note I extended \PHPUnit_Extensions_Selenium2TestCase
$form = $this->byId('login-form');
$this->assertEqual('/post/login', $form->attribute('action'));
It seems like action always null.
Does anyone know how to test the form action attribute?
Thank you.
Unfortunately, $form->attribute('action') returns action with base url (http://localhost/post/login).
I did not find a way to get action without base and did not find how to get base url. There is my solution:
function testForm(){
$this->url('/test.html');
$form = $this->byId('login-form');
$this->assertEquals('/post/login', $this->getRelativeFormAction($form));
}
function getRelativeFormAction($form){
$action = $form->attribute('action');
$action = str_replace($this->getBaseUrl(), '', $action);
return $action;
}
function getBaseUrl(){
$urlComponents = parse_url($this->url());
$url = "{$urlComponents['scheme']}://{$urlComponents['host']}";
return $url;
}
There is successful full test code.