Firstly Im new to CodeIgniter and MVC.
I am Creating a CMS and coudln't decide which route to take with do I have two applications (front end/CMS) or just create the admin as a controller. I opted for one application and creating the admin via a Controller.
Doing it this way I have ran into a problem with form validation where if it doesn't validate I cant load the form I have to redirect which then means it wont repopulate the unvalidated fields. I use a variable in the 3rd URI segment to determine whether to display a form for inserting a new record, a populated form for editing a record, or a tabled list of all records.
The form posts to /admin/videos/save
function videos()
{
if (!$this->tank_auth->is_logged_in()) {
redirect('/auth/login/');
} else {
$this->load->model('videos_model');
$data['section'] = "Videos";
$data['area'] = "Videos";
$data['mode'] = $this->uri->segment(3, 'create');
$data['user_id'] = $this->tank_auth->get_user_id();
$data['username'] = $this->tank_auth->get_username();
if ($data['mode'] == 'edit') {
$data['ID'] = $this->uri->segment(4);
$data['videos'] = $this->videos_model->get_videos($data['ID']);
} elseif ($data['mode'] == 'list') {
if ($this->uri->segment(4)) {
$data['filter'] = $this->uri->segment(4);
$data['videos'] = $this->videos_model->get_filtered_videos($data['filter']);
} else {
$data['videos'] = $this->videos_model->get_filtered_videos();
}
} elseif ($data['mode'] == 'save') {
$this->load->helper('form');
$this->load->library('form_validation');
$this->form_validation->set_rules('videoTitle', 'Title', 'required');
$this->form_validation->set_rules('Code', 'Youtube Code', 'required');
if ($this->form_validation->run() === FALSE) {
redirect('/admin/videos');
} else {
$this->videos_model->set_videos();
redirect('/admin/videos/list');
}
}
if ($data['mode'] != "create" && empty($data['videos'])) {
show_404();
}
$this->load->view('admin/templates/head', $data);
$this->load->view('admin/templates/body_navbar', $data);
$this->load->view('admin/videos', $data);
$this->load->view('admin/templates/footer', $data);
}
}
Am I setting about this the wrong way, Should I use two application folders or have 3 controllers for editing/inserting/viewing all. Or is there a solution to my current setup?
I personally haven't used CodeIgniter's form helper nor validation lib, so excuse my ignorance, but is there any particular reason you're not doing this as AJAX post instead?
Am I setting about this the wrong way, Should I use two application
folders or have 3 controllers for editing/inserting/viewing all. Or is
there a solution to my current setup?
Why 3 controllers? You can have a single controller with multiple functions. Honestly, I'd recommend just doing a simple AJAX post on your form and returning some JSON data whether validation passed or not -- no need for redirects.
Something like:
// AJAX
function validateForm() {
$.post('route/to/controller', {"apple": appleValue, "peach": peachValue}, function(data) {
json = $.parseJSON(data);
if (json.success)
alert('Great!');
else
alert('Nope!');
});
//Controller
function validateForm()
{
$data['success'] = ...validation checks...
echo json_encode($data);
}
I have continued to use my one application folder and the entire admin as a controller.
I have solved my form validation and repopulating issue by continuing to redirect back to the form but storing the form fields and errors in a session.
I destroy the error data in the session once viewed but leave the other info intact which allows the user to navigate away and come back and the info will remain. Once the form is validated correctly and information stored in the database it destroys the session data.
function videos()
{
if (!$this->tank_auth->is_logged_in()) {
redirect('/auth/login/');
} else {
$this->load->model('videos_model');
$data['section'] = "Videos";
$data['area'] = "Videos";
$data['mode'] = $this->uri->segment(3, 'create');
$data['user_id'] = $this->tank_auth->get_user_id();
$data['username'] = $this->tank_auth->get_username();
if ($this->session->userdata('videoTitle'))
$data['videoTitle'] = $this->session->userdata('videoTitle');
if ($this->session->userdata('Code'))
$data['Code'] = $this->session->userdata('Code');
if ($this->session->userdata('videoTitle'))
$data['description'] = $this->session->userdata('description');
if ($this->session->userdata('errors')){
$data['errors'] = $this->session->userdata('errors');
$this->session->unset_userdata('errors');
}
if ($data['mode'] == 'edit') {
$data['ID'] = $this->uri->segment(4);
$video_data = $this->videos_model->get_videos($data['ID']);
$data['videoTitle'] = $video_data['videoTitle'];
$data['Code'] = $video_data['blipCode'];
$data['description'] = $video_data['description'];
} elseif ($data['mode'] == 'list') {
if ($this->uri->segment(4)) {
$data['filter'] = $this->uri->segment(4);
$data['videos'] = $this->videos_model->get_filtered_videos($data['filter']);
} else {
$data['videos'] = $this->videos_model->get_filtered_videos();
}
} elseif ($data['mode'] == 'save') {
$this->load->helper('form');
$this->load->library('form_validation');
$this->form_validation->set_rules('videoTitle', 'Title', 'required');
$this->form_validation->set_rules('Code', 'Youtube Code', 'required');
if ($this->form_validation->run() === FALSE) {
$formdata = array(
'videoTitle' => $this->input->post('videoTitle'),
'Code' => $this->input->post('Code'),
'description' => $this->input->post('description'),
'errors' => validation_errors()
);
$this->session->set_userdata($formdata);
redirect('/admin/videos');
} else {
$this->videos_model->set_videos();
$this->session->unset_userdata('videoTitle');
$this->session->unset_userdata('Code');
$this->session->unset_userdata('description');
redirect('/admin/videos/list');
}
}
$this->load->view('admin/templates/head', $data);
$this->load->view('admin/templates/body_navbar', $data);
$this->load->view('admin/videos', $data);
$this->load->view('admin/templates/footer', $data);
}
}
Related
I am a beginner of Codeigniter 3. I am trying to submit two form values in a view. Here is the code:
<?php
class User extends CI_Controller{
public function __construct(){
parent::__construct();
if(!isset($_SESSION['user_logged'])){
redirect("auth/login","refresh");
}
}
public function profile(){
$this->load->view('profile');
}
public function members(){
if ($this->input->post('promote')!==FALSE){
$this->form_validation->set_rules('username','Userpromote','required');
if($this->form_validation->run() == TRUE){
$data = array(
'subadmin' => $_POST['username']
);
$this->db->insert('sub', $data);
redirect("user/members", "refresh");
}
} elseif ($this->input->post('demote')!==FALSE){
$this->form_validation->set_rules('subdemote','Userdemote','required');
if($this->form_validation->run() == TRUE){
$data2 = $_POST['subdemote'];
$this->db->delete('sub', array('subadmin' => $data2 ));
redirect("user/members", "refresh");
}
}
$this->load->view('members');
}
public function products(){
$this->load->view('products');
}
}
But problem is, only 'promote' part works, but the 'demote' portion doesn't. If i erase the 'promote' part, the 'demote' park work fine. Could you please tell me what i'm doing wrong ?
It seems to me that you have a logic problem. You have the 'demote' code on a else if block, which means once the if statement is satisfied the else if won't be reached at all. Also you are using redirect on the end of the statements, which means you'll be redirected on that moment and the rest of the script won't be executed. You might try two sepparate if's like this:
public function members(){
if ($this->input->post('promote')!==FALSE){
$this->form_validation->set_rules('username','Userpromote','required');
if($this->form_validation->run() == TRUE){
$data = array(
'subadmin' => $_POST['username']
);
$this->db->insert('sub', $data);
//redirect("user/members", "refresh");
}
}
if ($this->input->post('demote')!==FALSE){
$this->form_validation->set_rules('subdemote','Userdemote','required');
if($this->form_validation->run() == TRUE){
$data2 = $_POST['subdemote'];
$this->db->delete('sub', array('subadmin' => $data2 ));
//redirect("user/members", "refresh");
}
}
$this->load->view('members');
}
I'm getting error when login to my project and then goto the base url. The below is the error which i get
My Login page [ see the url ]
After logging in , if i remove the highlighted segments[pls see below image] after which i get the above error
I know these error are due to headers so can somebody help me in saying what error am i making in header. An also say how to make good use of session so that the form is to resubmitted when i refresh after logging in. Below are the header codes.
login header
<?php if(isset($this->session->userdata['logged'])){
header("location: http://localhost/capacity_planner/login/login_check");
}
?>
admin dashboard[after logging in header]
<?php if(isset($this->session->userdata['logged'])){
$email = ($this->session->userdata['logged']['email']);
}else{
header("location: http://localhost/capacity_planner/login");
}
?>
controller side
public function login_check(){
$data['base_url'] = base_url();
$this->form_validation->set_rules('email', 'Email', 'trim|required|xss_clean');
$this->form_validation->set_rules('password', 'Password', 'trim|required|xss_clean|callback_check_database');
if ($this->form_validation->run($this) == false) {
$this->index();
} else {
if(isset($this->session->userdata['logged'])) {
$data['login_bg'] = $this->input->post('login_bg');
$this->load->view("admin_db", $data);
}
}
function check_database($password){
$email= $this->input->post('email');
$user = $this->user->loginCheck($email, $password);
if($user[1] == 1){
$result = $this->user->user_details($email);
if($result != false) {
$session_data = array(
'id' => $result[0]->id,
'email' => $result[0]->cp_email,
);
$this->session->set_userdata('logged', $session_data);
return true;
}
} else{
$this->form_validation->set_message('check_database', $user[0]);
return false;
}
}
ERR_TOO_MANY_REDIRECTS is caused when strucked up in a conditional loop
I assume you want to redirect to admin dashboard if you go to index after logged in..
Try adding these lines in your public function index()
public function index(){
if(isset($this->session->userdata['logged'])) {
//admin_db display function eg.redirect('admindashboard');
}
else{
//load your index view
this->load->view('your_index_view');
}
}
or you can check reverse way in admin dashboard function like this
public function dashboard(){
if($this->session->userdata('logged') == ''){
redirect('index');
}
else{
$this->load->view('dashboard view');
}
}
This is my assumption.Kindly check it.
I am building a bundle for private messages between my users.
Here is my inbox action from my controller. What it does is fetches the current user's messages, it passes the query to KNPpaginator to display a part of them. I also save how many results to be displayed on the page in the database. One form is a dropdown that sends how many results to display per page. The other form is made of checkboxes and a dropdown with actions. Based on which action was selected, I pass the id's of the messages(selected checkboxes id's) to another function called markAction(which is also a page that can mark one single message by going to the specific url)
public function inboxAction(Request $request)
{
$messages = $this->getDoctrine()->getRepository('PrivateMessageBundle:Message');
$mymsg = $messages->findMyMessages($this->getUser());
$message_settings = $this->getDoctrine()->getRepository('PrivateMessageBundle:MessageSettings');
$perpage = $message_settings->findOneBy(array('user' => $this->getUser()));
$pagerform = $this->createForm(new MessageSettingsType(), $perpage);
$pagerform->handleRequest($request);
if ($pagerform->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($perpage);
$em->flush();
}
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$mymsg,
$request->query->get('page', 1)/*page number*/,
$perpage ? $perpage->getResPerPage() : 10/*limit per page*/,
array('defaultSortFieldName' => 'a.sentAt', 'defaultSortDirection' => 'desc')
);
$form = $this
->createForm(
new ActionsType(),
$mymsg->execute()
);
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
$ids = array();
foreach ($data['checkboxes'] as $checkbox) {
$ids[] = $checkbox->getId();
}
$action = $data['inboxactions'];
$this->markAction($action, $ids);
return $this->redirectToRoute('private_message_inbox');
}
return $this->render(
'#PrivateMessage/inbox.html.twig',
array(
'messageList' => $pagination,
'form' => $form->createView(),
'pagerform' => $pagerform->createView(),
)
);
}
And the mark action user in my inbox controller. Based on one parameter, I apply the respective action to the second parameter, which is one message if the page was called through routing, and can be an array of messages if called through my inboxAction. I do a few consistency checks, and then mark my message.
public function markAction($action, $msgs)
{
if (!$msgs) {
$this->addFlash(
'error',
'Select at least one message!'
);
return;
} else {
if (!$action) {
$this->addFlash(
'error',
'Select one action to apply to your items!'
);
return;
} else {
$messages = $this->getDoctrine()->getRepository('PrivateMessageBundle:Message');
$em = $this->getDoctrine()->getManager();
$msg = $messages->findBy(array('receiver' => $this->getUser(), 'id' => $msgs));
$good = 0;
foreach ($msg as $isforme) {
$good++;
switch ($action) {
case 'spam': {
if ($isforme->getIsSpam() == false) {
$isforme->setIsSpam(true);
if (!$isforme->getSeenAt()) {
$isforme->setSeenAt(new \DateTime('now'));
}
$em->persist($isforme);
}
break;
}
case 'unspam': {
if ($isforme->getIsSpam() == true) {
$isforme->setIsSpam(false);
$em->persist($isforme);
}
break;
}
case 'viewed': {
if ($isforme->getSeenAt() == false) {
$isforme->setSeenAt(new \DateTime('now'));
$em->persist($isforme);
}
break;
}
case 'unviewed': {
if ($isforme->getSeenAt() != false) {
$isforme->setSeenAt(null);
$em->persist($isforme);
}
break;
}
default: {
$this->addFlash(
'error',
'There was an error!'
);
return;
}
}
$em->flush();
}
$this->addFlash(
'notice',
$good.' message'.($good == 1 ? '' : 's').' changed!'
);
}
}
if ($action == 'unspam') {
return $this->redirectToRoute('private_message_spam');
} else {
return $this->redirectToRoute('private_message_inbox');
}
}
Being kind of new to symfony, I'm not sure how good my markAction function is. I feel like it can be simplier, but I'm not sure how to make it.
Now, my actual question. How can I render other pages of my bundle, like Sent or Spam messages? The only lines from the inboxAction that I have to change are
$mymsg = $messages->findMyMessages($this->getUser());
to have it return spam or sent messages by the user, for instance.
and
return $this->render(
'#PrivateMessage/inbox.html.twig',...
so I actually return the respective page's view. I have already made the other pages and copied the code in the other actions, but I think I can make it so I write this code a single time, but don't know how.
Everything else is EXACTLY the same. How can I not copy and paste this code in all of the other actions and make it a bit more reusable?
You could strart to change your routing more dynamic:
# app/config/routing.yml
mailclient:
path: /mailclient/{page}
defaults: { _controller: AppBundle:Mailclient:index, page: "inbox" }
Resulting that this routes:
/mailclient
/mailclient/inbox
/mailclient/sent
/mailclient/trash
will all call the same action.
Now your method (Action) will get an extra parameter:
public function indexAction($page, Request $request)
{
// ...
}
Through this parameter you know what the user likes to see. Now you can start to write your code more dynamic. You can consider to add some private functions to your controller class that you can call from the indexAction or
you could simply create your own classes too.
I am trying to add a captcha for my login form in codeigniter.
The captcha is displaying fine. and problem is in verifying it.
When validate_captcha is being called the value from input post is correct but session value is new page value.(For example , if on the 1st page load captcha was 12345 (let's assume in second load it will be 54321) . then when in first load user inputs 12345 it will be checked with 54321.
What can I do?
Here is what I have tried
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Login extends CI_Controller
{
public function index()
{
$capCode = rand(10000, 99999);
$this->session->set_userdata(array('captcha'=>$capCode));
echo $this->session->userdata['captcha'];//for debug only
$this->load->helper('captcha');
$vals = array(
'word' => $capCode ,
'img_path' => CAPTCHA_PATH,
'img_url' => base_url().CAPTCHA_PATH,
'img_width' => '150',
'img_height' => 30,
'expiration' => 1200
);
$cap = create_captcha($vals);
$data = array('un' => $un,'defTab'=>'','captcha'=>$cap);
$this->load->library('form_validation');
//I need to load different data if form is result of a post($data['defTab'])
if($this->input->post('submit'))
{
$this->form_validation->set_rules('email', 'Email', 'required|valid_email');
$this->form_validation->set_rules('captcha', 'Captcha', 'required|callback_validate_captcha');
if ($this->form_validation->run() == FALSE)
{
$data['defTab'] = 'what i need';
$this->load->view('login',$data);
}
else
{
print_r($this->input->post());
}
}
else
{
$this->load->view('login',$data);
}
}
public function validate_captcha()
{
$sss=$this->input->post('captcha');
//I Use this line to find problem
$this->form_validation->set_message('validate_captcha', 'session:'.$this->session->userdata['captcha'].'\nPosted val:'.$sss);
if($sss!= $this->session->userdata['captcha'])
{
return false;
}
else
{
return true;
}
}
}
You have to set the session during creation of your form:
.
.
.
} else {
if (isset($cap["word"])) {
$this->session->set_userdata("word", $cap["word"]);
}
$this->load->view('login',$data);
}
And during the validation check it with:
if($this->input->post("word", TRUE) == $this->session->userdata("word")){
// do something
}
Before calling the create_captcha method use the below code to set the previous captcha
$this->session->set_userdata('prev_captcha',$this->session->userdata('captcha_word'));
provided captcha_word contains current captcha
and check like below
function checkCaptcha($str){
$word = $this->session->get('prev_captcha');
if(strcmp(strtoupper($str),strtoupper($word)) == 0){
return true;
}else{
return false;
}
}
I have a weird bug.
Form validation is doing both TRUE and FALSE actions.
For TRUE, the database model (scrape_url_model) runs so the database is updated, but then the views are run as though form validation is FALSE.
The FALSE view (scrape_url/index) is shown instead of the view associated with a successful validation (scrape_url/form_success).
I'm getting the validation error message The URL is already in the database from the callback function.
public function index(){
$this->load->helper('form');
$this->load->library('form_validation');
$this->form_validation->set_error_delimiters('', '');
$data['pageTitle'] = 'URL Scraping Tool';
$this->form_validation->set_rules('event_url', 'URL', 'trim|required|callback_url_check');
if ($this->form_validation->run() == FALSE){
$this->load->view('templates/header', $data);
$this->load->view('scrape_url/index', $data);
$this->load->view('templates/footer');
}
else {
$this->load->library('Db_queries');
$this->load->library('session');
$this->load->helper('url');
list($session_data['alert'],
$session_data['alert_type'],
$session_data['countUncategorizedDecks'],
$session_data['event_id'],
$session_data['eventDate']) = $this->scrape_url_model->insert_decks_and_cards();
if ($this->input->post('last_url') == 'yes'){
$this->scrape_url_model->insert_md_percentage($session_data['eventDate']);
}
$this->session->set_userdata($session_data);
$this->load->view('templates/header', $data);
$this->load->view('scrape_url/form_success', $data);
$this->load->view('templates/footer_ajax');
}
}
public function url_check($event_url) {
$url_regex = "/^(http|https|ftp):\/\/([A-Z0-9][A-Z0-9_-]*(?:\.[A-Z0-9][A-Z0-9_-]*)+):?(\d+)?\/?/i";
if (preg_match($url_regex, $event_url) == FALSE) {
// check to see if input is a URL
$this->form_validation->set_message('url_check', 'Please enter a URL including "http://".');
return FALSE;
}
$this->load->database();
$sql = 'SELECT url FROM event';
$s = $this->db->conn_id->query($sql);
$used_urls = $s->fetchAll(PDO::FETCH_COLUMN, 0);
if (in_array($event_url, $used_urls)){
$this->form_validation->set_message('url_check', 'The URL is already in the database.');
return FALSE;
}
return TRUE;
}
Try using statement:
$this->form_validation->run() == true
and then code your conditions accordingly. It will work and will also easy to understand.