I'm working with Symfony 3.1
My issue : When I use 2 forms on the same page, only first one works
Details:
On my home page, I have a contact form and a comment form.
They are not link, and use differents entities.
They are called via two different renderController.
Forms are created with FormBuilder and submitted via AJAX
I found an article where they say to use createNamedBuilder, but still not working.
If only one form is active, then it works. If both are active, then only the first one works.
The second one send a POST method but do not submit the form
I'm looking for a solution since many days but still nothing.. please HELP !!!
Many thanks
Olivia
view.html.twig
{{ render(controller('BecowoCoreBundle:Workspace:contact', {name: ws.name})) }}
{{ render(controller('BecowoCoreBundle:Booking:bookingList', {name: ws.name})) }}
contact Controller :
public function contactAction($name, Request $request)
{
$contact = new Contact();
// $managerContactForm = $this->createForm(ManagerContactType::class, $contact);
$managerContactForm = $this->get('form.factory')->createNamedBuilder('manager_contact', ManagerContactType::class, $contact)->getForm();
$WsService = $this->get('app.workspace');
$ws = $WsService->getWorkspaceByName($name);
$wsHasTeamMembers = $WsService->getWsHasTeamMemberByWorkspace($ws);
$emailManager = [];
$i = 0;
if($wsHasTeamMembers == null or $this->container->get( 'kernel' )->getEnvironment() != 'prod')
{
$emailManager[0] = 'test#test.com';
}else{
foreach ($wsHasTeamMembers as $wsHasTeamMember ) {
$emailManager[$i] = $wsHasTeamMember->getTeamMember()->getEmail();
$i ++;
}
}
// On vérifie que c'est bien le form de contact manager qui est envoyé
if ($request->isMethod('POST') && $managerContactForm->handleRequest($request)->isValid() && $request->request->has('manager_contact')) {
$message = \Swift_Message::newInstance()
->setSubject('Becowo - Nouveau message d\'un coworker')
->setFrom('test#test.com')
->setTo($emailManager)
->setBody(
$this->renderView(
'CommonViews/Mail/Manager-contact.html.twig',
array(
'name' => $managerContactForm->get('name')->getData(),
'email' => $managerContactForm->get('email')->getData(),
'subject' => $managerContactForm->get('subject')->getData(),
'message' => $managerContactForm->get('message')->getData()
)
)
);
$this->get('mailer')->send($message);
$session = $request->getSession();
$session->set('contactManager', 'ok');
return $this->redirectToRoute('becowo_core_workspace_contact', array('name' => $name));
}
return $this->render('Workspace/manager-contact.html.twig',
array('managerContactForm' => $managerContactForm->createView(),
'name' =>$name));
}
Comment controller :
public function viewAction(Request $request)
{
$WsService = $this->get('app.workspace');
$ws = $WsService->getWorkspaceByName($request->get('name'));
$listComments = $WsService->getCommentsByWorkspace($ws);
$voteAlreadyDone = $WsService->memberAlreadyVoteAndCommentForWorkspace($ws, $this->getUser());
$comment = new Comment($ws, $this->getUser());
$formComment = $this->get('form.factory')->createNamedBuilder('comment', CommentType::class, $comment)->getForm();
if ($request->isMethod('POST') && $formComment->handleRequest($request)->isValid() && $request->request->has('comment'))
{
$em = $this->getDoctrine()->getManager();
$em->persist($comment);
$em->flush();
$this->addFlash('success', 'Merci ! Commentaire et vote bien enregistrés.');
return $this->redirectToRoute('becowo_comment', array('name' => $request->get('name')));
}
return $this->render('Workspace/comments.html.twig', array('formComment' => $formComment->createView(), 'listComments' => $listComments, 'ws' =>$ws, 'voteAlreadyDone' => $voteAlreadyDone));
}
Submit forms via AJAX :
// Page d'un WS, envoye le commentaire et le vote en AJAX
$(function () {
$("#comment_Envoyer").unbind("click").click(function(){
$.ajax(Routing.generate('becowo_comment', {name: document.getElementById('wsName').innerHTML}), {
data: $('#comment-form').serialize(),
type: "POST",
success: function(data) {
$('#CommentResults').html(data);
},
error: function() {
$('#CommentResults').html("Une erreur est survenue, veuillez réessayer plus tard");
}
});
return false;
});
});
// Page d'un WS, envoye le formulaire de contact manager en AJAX
$(function () {
$("#submitContactManager").unbind("click").click(function(){
$.ajax(Routing.generate('becowo_core_workspace_contact', {name: document.getElementById('wsName').innerHTML}), {
data: $('#manager-contact-form').serialize(),
type: "POST",
success: function(data) {
$('#modal-body-manager-contact').html(data);
},
error: function() {
$('#modal-body-manager-contact').html("Une erreur est survenue, veuillez réessayer plus tard");
}
});
return false;
});
});`enter code here`
Build your forms as Class.
http://symfony.com/doc/current/forms.html#creating-form-classes
Create your forms in controller by
controller method $this->createForm(....);
as example from Book
public function newAction()
{
$task = ...;
$form = $this->createForm(TaskType::class, $task);
// ...
}
pay attention on FORM name!
public function getName()
{
return 'payments';
}
You MUST have different form name for your forms in the same page!
Do not generate routes in JQuery, just set action for your form in Form class or in Twig and take action from Form directly.
Your ajax code in this case something like this:
$("#form_id_first, #form_id_second").submit(function (e){
e.preventDefault();
$form = $(e.target);
$ajax($form.attr('action')) {
...some: code,
data: $form.serialize(),
...some: code
}
});
Finally - don'y use for one Form - one Controller. Create several forms in one controller with different names and render them, or create Twig Extention, but handle in same place all it!
Symfony2 : Two forms in a same page
THANK YOU so much !!!!!
It's working :)
Carreful, 2 small mistakes in your JS code
$ajax should be $.ajax
I had to add 'type: "POST"' even if I setMethod in the controller
Here is the full code if someone face the same issue :
view.html.twig
{{ render(controller('BecowoCoreBundle:Workspace:contact', {name: ws.name})) }}
{{ render(controller('BecowoCoreBundle:Workspace:voteAndComment', {name: ws.name})) }}
workspace Controller (both forms have to be in same controller, but can be in different actions)
public function contactAction($name, Request $request)
{
$contact = new Contact();
$managerContactForm = $this->get('form.factory')->createNamedBuilder('manager-contact-form', ManagerContactType::class, $contact)
->setAction($this->generateUrl('becowo_core_workspace_contact', array('name' => $name)))
->setMethod('POST')
->getForm();
$WsService = $this->get('app.workspace');
$ws = $WsService->getWorkspaceByName($name);
$wsHasTeamMembers = $WsService->getWsHasTeamMemberByWorkspace($ws);
// On vérifie que c'est bien le form de contact manager qui est envoyé
if ($request->isMethod('POST') && $managerContactForm->handleRequest($request)->isValid() && $request->request->has('manager-contact-form')) {
$message = \Swift_Message::newInstance()
->setSubject('Becowo - Nouveau message d\'un coworker')
->setFrom('contact#becowo.com')
->setTo($emailManager)
->setBody(
$this->renderView(
'CommonViews/Mail/Manager-contact.html.twig',
array(
'name' => $managerContactForm->get('name')->getData(),
'email' => $managerContactForm->get('email')->getData(),
'subject' => $managerContactForm->get('subject')->getData(),
'message' => $managerContactForm->get('message')->getData()
)
)
);
$this->get('mailer')->send($message);
$this->addFlash('success', 'Merci ! Email bien envoyé.');
return $this->redirectToRoute('becowo_core_workspace_contact', array('name' => $name));
}
return $this->render('Workspace/manager-contact.html.twig',
array('managerContactForm' => $managerContactForm->createView(),
'ws' =>$ws));
}
public function voteAndCommentAction($name, Request $request)
{
$WsService = $this->get('app.workspace');
$ws = $WsService->getWorkspaceByName($request->get('name'));
$listComments = $WsService->getCommentsByWorkspace($ws);
$voteAlreadyDone = $WsService->memberAlreadyVoteAndCommentForWorkspace($ws, $this->getUser());
// Création du formulaire de commentaires
$comment = new Comment($ws, $this->getUser());
$formComment = $this->get('form.factory')->createNamedBuilder('comment-form', CommentType::class, $comment)
->setAction($this->generateUrl('becowo_comment', array('name' => $name)))
->setMethod('POST')
->getForm();
if ($request->isMethod('POST') && $formComment->handleRequest($request)->isValid() && $request->request->has('comment-form'))
{
$em = $this->getDoctrine()->getManager();
$em->persist($comment);
$em->flush();
$this->addFlash('success', 'Merci ! Commentaire et vote bien enregistrés.');
return $this->redirectToRoute('becowo_comment', array('name' => $request->get('name')));
}
return $this->render('Workspace/comments.html.twig', array('formComment' => $formComment->createView(), 'listComments' => $listComments, 'ws' =>$ws, 'voteAlreadyDone' => $voteAlreadyDone));
}
Submits forms via AJAX :
$("#manager-contact-form").submit(function (e){
e.preventDefault();
$form = $(e.target);
$.ajax($form.attr('action'), {
data: $form.serialize(),
type: "POST",
success: function(data) {
$('#contentToRefresh').html(data);
},
error: function() {
$('#contentToRefresh').html("Une erreur est survenue, veuillez réessayer plus tard");
}
});
});
$("#comment-form").submit(function (e){
e.preventDefault();
$form = $(e.target);
$.ajax($form.attr('action'), {
data: $form.serialize(),
type: "POST",
success: function(data) {
$('#CommentResults').html(data);
},
error: function() {
$('#CommentResults').html("Une erreur est survenue, veuillez réessayer plus tard");
}
});
});
Related
I am using REST API in my project and everything works great. I describe a model using a model
<?php
namespace api\modules\v1\models;
use Carbon\Carbon;
use Yii;
class Comment extends \common\models\Comment
{
public function fields()
{
return [
'id',
'user' => function(Comment $model) {
return User::findOne($model->user_id);
},
'text',
'image' => function(Comment $model) {
return Yii::$app->params['link'].$model->image;
},
'created_at' => function(Comment $model) {
Carbon::setLocale(Yii::$app->language);
return Carbon::createFromTimeStamp(strtotime($model->created_at))->diffForHumans();
},
'children' => function(Comment $model) {
$comments = Comment::find()
->where(['comment_id' => $model->id]);
if (!$comments->exists()) {
return false;
}
return $comments->all();
},
'like',
'news_id',
'comment_id'
];
}
}
The data is returned in the specified format and that's great. But I need to send data to the controller using websockets. For example, when a new comment arrives, send it to all users.
$post = Yii::$app->request->post();
$image = UploadedFile::getInstanceByName('image');
$model = new \api\modules\v1\models\Comment([
'news_id' => $post['feed_id'],
'comment_id' => $post['comment_id'] ?? null,
'user_id' => Yii::$app->user->identity->id,
]);
$model->text = $model->findLinks($post['text']);
if ($image && !$image->error) {
if (!file_exists(Yii::$app->params['comment.pathAbsolute'])) {
if (!FileHelper::createDirectory(Yii::$app->params['comment.pathAbsolute'], 0777)) {
throw new \Exception('Помилка створення папки');
}
}
$serverName = Yii::$app->security->generateRandomString(16).'.'.$image->extension;
if ($image->saveAs(Yii::$app->params['comment.pathAbsolute'].$serverName)) {
$model->image = $serverName;
} else {
throw new \Exception($image->error);
}
}
if (!$model->save()) {
throw new \Exception($model->error());
}
Helper::ws(false, 'updateComment', ['feed_id' => $post['feed_id'], 'comment' => $model]);
And when I pass the $model, the data is passed as it is stored in the database. Is it possible to call a method or something so that the data is passed as I described in the model api?
A PHP Error was encountered
Severity: Warning
Message: ini_set(): A session is active. You cannot change the session module's ini settings at this time
Filename: Session/Session.php
Line Number: 316
Backtrace:
File: C:\xampp\htdocs\testing\index.php
Line: 315
Function: require_once
<?php
session_start(); //we need to start session in order to access it through CI
class Adminlogin extends CI_Controller {
public function _construct(){
parent::_construct();
//Load form helper library
$this->load->helper('form');
//Load form validation library
$this->load->library('form_validation');
//Load session library
$this->load->library('session');
//Load database
$this->load->model('login_database');
}
//show login page
public function index()
{
$this->load->view('admin_login');
}
//show registration page
public function user_registration_show(){
$this->load->view('admin_signup');
}
//Validate and store registration data in database
public function new_user_registration(){
//Check Validation for user input in SignUp form
$this->form_validation->set_rules('admin_username', 'Username','trim|required|xss_clean');
$this->form_validation->set_rules('admin_password', 'Password','trim|required|xss_clean');
if($this->form_validation->run()== FALSE){
$this->load->view('admin_signup');}
else{
$data = array(
'admin_username' => $this->input->post('username'),
'admin_password' => $this->input->post('password'));
$result = $this->login_database->registration_insert($data);
if($result == TRUE){
$data['message_display'] = 'Registration Successfully !';
$this->load->view('admin_login', $data);
}else{
$data['message_display'] = 'Username already exist';
$this->load->view('admin_signup',$data);
}
}
}
//Check for user login process
public function user_login_process(){
$this->form_validation->set_rules('admin_username','Username', 'trim|required|xss_clean');
$this->form_validation->set_rules('admin_password','Password', 'trim|required|xss_clean');
if($this->form_validation->run() == FALSE){
if(isset($this->session->userdata['loggen_in'])){
$this->load->view('Admin/admin_dashboard');
}else{
$this->load->view('admin_login');
}
}else{
$data = array(
'admin_username' => $this->input->post('username'),
'admin_password' => $this->input->post('password'));
$result = $this->login_database->login($data);
if($result == TRUE) {
$username = $this->input->post('username');
$result = $this->login_database->read_user_information($username);
if($result != false){
$session_data = array(
'username' => $result[0]->admin_username,
'password' => $result[0]->admin_password);
//Add user data in session
$this->session->set_userdata('logged_in', $session_data);
$this->load->view('Admin/admin_dashboard');
}else{
$data = array(
'error_message' => 'Invalid Username or Password');
$this->load->view('admin_login',$data);
}
}
}
}
}
?>
Please remove the 1st line session_start(); or change it to..
// session_start(); //I do Not need this as I am using CI Sessions.
You are using CodeIgniters Sessions which you have loaded in your code...
$this->load->library('session');
As an Aside:
You don't need the end ?> in your PHP files where it is the last tag in the file.
I have problem with save method of collections in Phalcon.It doesn't work and doesn't give me any errors or something.I want to create a Micro App with mongoDb:
Phalcon version: 1.3.4
php : 5.5.9
Here are the registered services:
<?php
use Phalcon\DI\FactoryDefault,
Phalcon\Assets\Manager as AssetsManager,
Phalcon\Mvc\Collection\Manager as CollectionManager,
Phalcon\Mvc\View\Simple as View,
Phalcon\Mvc\View\Engine\Volt,
Phalcon\Mvc\Url as UrlResolver,
Phalcon\Flash\Session as Flash,
Phalcon\Flash\Direct as FlashDirect,
Phalcon\Session\Adapter\Files as Session;
$di = new FactoryDefault();
$di['url'] = function () {
$url = new UrlResolver();
$url->setBaseUri('/dasshy/');
return $url;
};
/**
* Flash service with custom CSS classes
*/
$di['flash'] = function () {
return new Flash(array(
'error' => 'alert alert-error',
'success' => 'alert alert-success',
'notice' => 'alert alert-info',
));
};
/**
* Flash service with custom CSS classes
*/
$di['flashDirect'] = function () {
return new FlashDirect(array(
'error' => 'alert alert-error',
'success' => 'alert alert-success',
'notice' => 'alert alert-info',
));
};
$di['session'] = function () {
$session = new Session(array(
'uniqueId' => 'dasshy-'
));
$session->start();
return $session;
};
$di['mongo'] = function () {
$mongo = new MongoClient();
return $mongo->selectDb("stats");
};
$di->set('collectionManager', function () {
return new Phalcon\Mvc\Collection\Manager();
});
I want to use the ODM, so here is the model Collection:
<?php
namespace Dasshy\Models;
class Messages extends \Phalcon\Mvc\Collection
{
public $content;
public $senderId;
public $receiverId;
public $date;
}
And here how i use it at handlers.php:
<?php
use Dasshy\Models\Messages;
use Phalcon\Mvc\Micro\Collection;
$app->map('/send/{receiverId}/{senderId}/{content}', function ($receiverId, $senderId, $content) use ($app) {
$messageModel = new Messages();
$messageModel->receiverId = $receiverId;
$messageModel->senderId = $senderId;
$messageModel->content = $content;
$messageModel->date = date('Y-m-d H-i-s', time());
$messageModel->save();
if ($messageModel->save() == false) {
echo "Umh, We can't store robots right now: \n";
foreach ($messageModel->getMessages() as $message) {
echo $message, "\n";
}
} else {
echo "Great, a new robot was saved successfully!";
}
});
$app->map('/messages', function () use ($app) {
var_dump(Messages::find());
exit;
});
you need to setup the mongo connection on the service...
$config = $di->getShared('config')->mongo;
$connect_data = $config->username . ':' . $config->password . '#' . $config->host . ':' . $config->port . '/' . $config->dbname;
$mongo = new \MongoClient("mongodb://" . $connect_data);
return $mongo->selectDB($config->dbname);
...since you are not connecting to any mongo server
I'm struggling to figure this out, but with everything I'm doing I am unable to fetch a users information. I simply get a 401 error and cannot figure out why.
Code:
<?php
class Tumblr
{
public function connect()
{
$tumblr = new ExternalExtended_Helper_Tumblr;
$oauth = $tumblr->getOauthConsumer('https://mysite.com/register');
$requestToken = $oauth->getRequestToken();
$accessToken = $oauth->getAccessToken($this->_input->filter(array(
'oauth_token' => XenForo_Input::STRING,
'oauth_verifier' => XenForo_Input::STRING
)), $requestToken);
$user = $tumblr->retrieveUserInfo($accessToken);
}
}
<?php
class Helper_Tumblr
{
/**
* Returns a reference to the OAuth consumer, instantiating it if necessary
*
* #param string $callbackUrl URL to return to
*
* #return bool|Zend_Oauth_Consumer False if no Tumblr app configured, otherwise Oauth consumer
*/
public static function getOauthConsumer($callbackUrl = '')
{
$options = XenForo_Application::getOptions();
if (!$options->tumblrAppKey || !$options->tumblrAppSecret)
{
return false;
}
return new Zend_Oauth_Consumer(array(
'callbackUrl' => $callbackUrl,
'requestTokenUrl' => 'https://www.tumblr.com/oauth/request_token',
'authorizeUrl' => 'https://www.tumblr.com/oauth/authorize',
'accessTokenUrl' => 'https://www.tumblr.com/oauth/access_token',
'consumerKey' => $options->tumblrAppKey,
'consumerSecret' => $options->tumblrAppSecret,
));
}
/**
* Returns a reference to the OAuth client, instantiating it if necessary
*
* #param string $accessToken Tumblr access token (from code swap, or given by user); may be empty
*
* #return bool|Zend_Oauth_Client False if no Tumblr app configured, otherwise Oauth client
*/
public static function getOauthClient($accessToken)
{
$options = XenForo_Application::getOptions();
if (!$options->tumblrAppKey || !$options->tumblrAppSecret)
{
return false;
}
$access = new Zend_Oauth_Token_Access();
$access->setToken($accessToken->getToken());
$access->setTokenSecret($accessToken->getToken());
return $access->getHttpClient(array(
'consumerKey' => $options->tumblrAppKey,
'consumerSecret' => $options->tumblrAppSecret
));
}
/**
* Get a User's Information
*
* #return json
*/
public static function retrieveUserInfo($accessToken)
{
$oauthClient = self::getOauthClient($accessToken);
$oauthClient->setUri('http://api.tumblr.com/v2/user/info');
$response = $oauthClient->request(Zend_Http_Client::POST);
if ($response->isError())
{
throw new Exception("An error occurred sending request. Status code: {$response->getStatus()}");
}
return $response;
}
}
The error occurs in the function 'retrieveUserInfo' and a dump of the object looks like this:
object(Zend_Http_Response)#280 (5) {
["version":protected] => string(3) "1.1"
["code":protected] => int(401)
["message":protected] => string(14) "Not Authorized"
["headers":protected] => array(7) {
["Server"] => string(5) "nginx"
["Date"] => string(29) "Mon, 17 Feb 2014 02:53:08 GMT"
["Content-type"] => string(31) "application/json; charset=utf-8"
["Transfer-encoding"] => string(7) "chunked"
["Connection"] => string(5) "close"
["Set-cookie"] => string(89) "tmgioct=53017993ddbda801421421421421; expires=Thu, 15-Feb-2024 02:53:07 GMT; path=/; httponly"
["P3p"] => string(46) "CP="ALL ADM DEV PSAi COM OUR OTRo STP IND ONL""
}
["body":protected] => string(71) "3c
{"meta":{"status":401,"msg":"Not Authorized"},"response":[]}
0
"
Why is it saying I'm not authorized and what haven't I done to become authorized?
Thanks!
Alright it's all fine, just a simple typo...
$access->setToken($accessToken->getToken());
$access->setTokenSecret($accessToken->getToken());
Should be:
$access->setToken($accessToken->getToken());
$access->setTokenSecret($accessToken->getTokenSecret());
Forgive my English.
I want to redirect not from action side but from a other function.
controller
public function editAction(Request $request, $id)
{
$em = $this->getDoctrine()->getEntityManager();
$article = $em->getRepository('MySampleBundle:Article')->find($id);
// TODO:
// Since other actions have the same processing,
// I would like to do check work in other function.
// And when inaccurate,
// I want to make it move from that function to other page.
$this->is_edit_granted($article);
$form = $this->createForm(new ArticleType(), $article);
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
// ...
}
}
return $this->render('MySampleBundle:Article:edit.html.twig', array(
'form' => $form->createView(),
'article' => $article,
));
}
public function is_edit_granted($article)
{
// TODO:
// I check not at the action side but at this place,
// and want to make it move from this function to other page.
if (!$article) {
throw $this->createNotFoundException('No article found.');
} else if ( $article->getAuthor() != $this->getUser()->getId() ) {
return $this->redirect( // doesn't work here
$this->generateUrl('home', array(
"id" => $article->getId()
))
);
}
}
I also tried similar code:
use Symfony\Component\HttpFoundation\RedirectResponse;
class SampleController extends Controller
{
// ...
public function editAction(Request $request, $id)
{
// ...
$this->is_edit_granted($article);
// ...
}
public function is_edit_granted($article)
{
if (!$article) {
throw $this->createNotFoundException('No article found.');
} else if ( $article->getAuthor() != $this->getUser()->getId() ) {
return new RedirectResponse(
$this->generateUrl('home', array(
"id" => $article->getId()
))
);
}
}
}
but it doesn't work.
It is performing in the environment of Symfony 2.1.2.
How can I manage to achieve that?
Or, is there any better method?
Do something like:
public function editAction(Request $request, $id)
{
// ...
$response = $this->is_edit_granted($article);
if ($response) return $response;
// ...
}
public function is_review_granted($article)
{
if (!$article) {
throw $this->createNotFoundException('No article found.');
} else if ( $article->getAuthor() != $this->getUser()->getId() ) {
return new RedirectResponse(
$this->generateUrl('home', array(
"id" => $article->getId()
))
);
}
return null;
}
It is not possible to redirect from the is_review_granted without returning the RedirectResponse form the editAction. So the answer of Carlos Granados is correct.
Another option would be to throw an AccessDeniedException in the is_review_granted method:
public function is_review_granted($article)
{
if (!$article) {
throw $this->createNotFoundException('No article found.');
} else if ( $article->getAuthor() != $this->getUser()->getId() ) {
throw new Symfony\Component\Security\Core\Exception\AccessDeniedException('no acces');
}
}
You could also look to some more in-depth solutions like ACL and SecurityVoters.