So my controller looks like this:
public function insert(){
//form_validation_rules
if($this->form_validation->run() == FALSE){
//redirect to view
}else{
//get data here $this->input->post()
//insert into table here all others depend on this table to exist
//returns story_id
if($table_id){
// here i have to insert data into 4 more table.
}
}
}
My erd looks like this:
So i have to insert into story table first since the story has to exist before i insert the genre/tags/content warning and finally the chapter since in my form to create a new story you have to add the first chapter too.
An answer to my previous question told me a nested if is bad practice and ive also searched here and saw this: PHP - Nested IF statements
My confusion is, where do i process and insert my data if i were to follow a scheme like that?
Writing this question up to here, my brain cleared up a bit, so i might aswell ask if i am right or in the right direction.
So i'll do it like this:
//process data here
$insert_genre = $this->model->insert_genre($genre);
$insert_tag = $this->model->insert_tags($tags);
$insert_warning = $this->model->insert_warning($content_warning);
$insert_chapter = $this->model->add_chapter($chapter);
if(!insert genre){
//redirect view }
if(!insert tags){
//redirect view }
if(!insert content_warning){
//redirect view }
if(!insert chapter){
//redirect view }
else{
//load view
}
EDIT:
This is how my model method for inserting genre/tag/contentwarning looks: theyre all similarly written.
public function new_story_genre($genre){
$inserted = 0;
foreach($genre as $row){
$this->db->insert('story_genre', $row);
$inserted += $this->db->affected_rows();}
if($inserted == count($genre)){
return TRUE;}else{ return FALSE; }
}
Nested if conditions are perfectly acceptable if they are not too many and if it is still easy to read.
You could easily nest your ifs here.
Personally i would use one if in this case:
// if insert errors: redirect view
if(!$insert_genre || !$insert_tags || !$insert_warning || !insert_chapter){
// redirect view
}
Pro tip: indent everything correctly, it helps wonders with readability of your code.
Edit:
you mentioned error strings in comments. Here is how you could structure your ifs with custom error strings:
if(!$insert_genre = $this->model->insert_genre($genre)){
redirect_view("Genre insert failed!");
}
if(!$insert_tags = $this->model->insert_tags($tags)){
redirect_view("Tags insert failed!");
}
public function redirect_view($errorString = ""){
// redirect view with individual error string
}
if you want you can also return an error string in the insert functions of the model. you have to change this code of the controller a bit but it would definately possible.
Related
I uploaded new rows into a table via my editor (SQLyog). The table already had data. The table was also indexed prior to the upload. After uploading the new data, when tasked to find the new data during testing, the code spits out the debug message, "No data" (see below), but it returns the pre-existing data just fine. Additionally, MySQL queries in the editor will return the new data.
If it matters, the table is a MyISAM table.
What should I be doing to allow the code/function to return the new data?
Here is the snippet of code that returns the debug message:
$code = $this->_addData($order_product['pid'],$order_product['qty'],$order_id);
$order_product['code'] = $code;
if(!$code) {
$this->log->debug('No data');
I have a feeling the answer lay in something I've not done in uploading the data or done incorrectly there, as the code works perfectly to find the existing data. Of course, I could be completely wrong.
EDIT: Below is the addData function. Obviously there are some additional function calls in there. Again, these all work fine for 'pre-existing' data in the table, but don't seem to find the 'new' rows of data.
protected function _addData($product_id,$quantity,$order_id){
$this->load->model('checkout/data');
if($this->model_checkout_data->productHasCampaign($product_id)){
$this->_hasData = true;
$codes = $this->model_checkout_data->checkAvailableData($product_id,$quantity);
//if there is data, update them
if(count($codes) == $quantity){
foreach($codes as $code){
$this->model_checkout_data->confirmCode($code['id'],$order_id);
}
} else {
//Redirect to Cart
$this->session->data['error_code'] = ERROR_OUT_OF_DATA;
header('Location: index.php?checkout/cart');
return;
}
$this->model_checkout_data->updateProductQuantity($product_id);
$this->_Data[$product_id] = $codes;
return $codes;
}
return false;
}
I have a function, that check user language and write it down in a variable. After a time, i come of idea to merge they, so that i need a call the function anytime before the first use of a variable, so i put a call of function inside of var, with a idea, that i would be replace it self. But it does not working, becouse it trying to give me a "Closure Object" back, i think it is a function in clear and not the result :( Here is the important part of code:
$GLOBALS['user_language'] = function()
{
return get_user_language();
}
function get_user_language()
{
$user_language = 'en';
$GLOBALS['user_language'] = $user_language;
return $user_language;
}
//somewhere in the script
print_r($GLOBALS['user_language']);
I wish to get 'en' out, nothing more.
function get_user_language()
{
$user_language = 'en';
$GLOBALS['user_language'] = $user_language;
return $user_language;
}
$GLOBALS['user_language'] = get_user_language();
//somewhere in the script
print_r($GLOBALS['user_language']);
But this is strange because you set it already in get_user_language() then you pull it again. It would almost create a loop. The proper way would probably be to remove the $GLOBALS['user_language'] = $user_language; from the function.
Hope this answers your question.
Just use print_r(get_user_language()) instead of print_r($GLOBALS['user_language']);.
If getting the user's language multiple times would be particularly slow (e.g. a database query would be executed over and over again), you can do something like this:
function get_user_language()
{
static $user_language = null;
if ($user_language === null) {
$user_language = 'en'; // this would be where you make the DB query
}
return $user_language;
}
In practice, in a large PHP application, this code would generally be located in a class and would store the value as an object property, so that, for example, the application can cache DB query results for multiple users rather than for only the current one.
Finally completed the frontend of my website, I am now looking at coding the backend which needs an overhaul, the coding is very messy and uses far too many SQL Connections and commands, so much so that the host is complaining about it.
One of the main problems I am having is the Site Settings page, problem is this page will soon contain over 10 different options, and I prefer not to have a MySQL Update simply updating the option field to what it already is, so I am wondering if anyone has any ideas?
This is the structure of my options table, nice and simple which I recently changed from an awful layout.
What would be the best way to edit these options without having to update every single one, and what would be the best way to have them in a function? Currently, the function I have was made back when I was new to coding, and you can see that is is very uneffective(note it uses the old table structure)
function site_upd($site_title, $site_email, $maint_status, $maint_mess, $upload_disable, $site_url, $reg_status, $land_mess)
{
if( !$site_title )
{
echo $this->errorMessage('There was no <b>site title</b> supplied, therefore we can not continue with this request.', 'error');
}
else
{
$this->logQuery('Updated site settings');
$query = "UPDATE `table`.`settings` SET `site_title` = '".$site_title."', `site_email` = '".$site_email."', `maint_status` = '".$maint_status."', `maint_mess` = '".$maint_mess."', `upload_disable` = '".$upload_disable."', `site_url` = '".$site_url."', `registration_status` = '".$reg_status."', `landing_mess` = '".$land_mess."' WHERE `settings`.`sid` = '1'";
mysql_query($query) or die(''.mysql_error()); } }
So yeah, there is the awful old structure and my old way of doing things, before I get stuck into coding I want other peoples opinions on what is the best way to do this!
You can work with $_POST Variable to simplify the update method.
This is what I usually do:
First I create a non specific function to update:
function update_db($table, $id,$idvalue,$field,$fieldvalue){
return mysql_query("update ".$table." set ".$field."=".$fieldvalue." where ".$id."=".$idvalue);
}
Then i create the specific function to the table (config i.e):
function update_table_config($name,$value){
return update_db("config","name",$id,"value",$value);
}
In the form i call all <input> like its name on the table:
Site Name: <input type="text" name="site_name">
...
and in the "action" page i check $_POST array:
$data_array=$_POST;
if(check_variables($data_array)){
foreach ($data_array as $key=>$value){
update_table_config($key,$value);
}
}
the function check_variables has all the checks that you need for all the fields:
function check_variables($data){
if($data["site_title"]=="") return false;
if(!is_numeric($data["landing_mess"])) return false;
...
return true;
}
with this methods if in the future you have to include more fields in the configuration table you only have to add the <input> field and a check in check_variables function if needed
I use the latest code igniter (2.0.3) and php-active 0.0.1.
All are working fine except save();
Code:
if($_POST)
{
$entry= Customers::find_by_routeid('4');
$entry->routeid=5;
$entry->save();
}
Here's my problem: for some reason that I cannot understand the above code does not work, but if I take the code out of if ($_POST), it works fine.
What I am doing wrong?
EDIT:
Thanks Damien Pirsy $this->input->post() does the trick, but when I uncomment the comments in the code the problems returns.
The code now is:
if($this->input->post())
{
$id = $this->input->post('id');
$oldRoute = $this->input->post('oldRoute');
$newRoute = $this->input->post('newRoute');
$entry= Customers::find_by_routeid($this->input->post('oldRoute'));
$entry->routeid=$this->input->post('newRoute');
$entry->save();
/*
if($oldRoute<$newRoute)
{
for ($i=$newRoute; $i>$oldRoute; $i--)
{
$element = Customers::find_by_routeid($i);
echo $element->routeid -= 1;
$element->save();
}
}
*/
}
The elements new IDs ($element->routeid -= 1;) are echoing right, but I have the same problem as in the beginning and neither of two saves work.
You didn't provide much details or debug info, so I'll just guess: try using the CI's native post handler instead. You should have var_dump()ed the $_POST array, see if isset() or not, also, since you're using it as a condition
if($this->input->post())
{
//...
}
UPDATE:
Since we're talking about Post variables, don't assume they're exactly as you want them. Keep in mind that $this->input->post('field') returns FALSE when the index is not present; that might well brake your if condition.
Assuming you need numbers to do this, you can do a check like
if($this->input->post('newRoute') AND is_numeric($this->input->post('newRoute'))
{
$newRoute = $this->input->post('newRoute');
}
else
{
// give it a default value, or raise an error, for example. If you need this
// variables, and need them to be numbers, you cannot go on in case these
// conditions are not met, right?
}
And the same for $oldRoute.
And yeah, OK, maybe you can write a cleaner code than mine, but you get the picture ;)
this is my front controller
$pages = array("matches", "boards", "search", "articles", "interviews", "userlist", "teams", "servers", "awards", "gallery", "qids");
if (!$_SERVER['QUERY_STRING']) include('home_en.php');
elseif (isset($_GET['matchid'])) include('matchid.php');
elseif (isset($_GET['boardid'])) include('boardid.php');
elseif (isset($_GET['articleid'])) include('articleid.php');
elseif (isset($_GET['interviewid'])) include('interviewid.php');
elseif (isset($_GET['userid'])) include('profi.php');
elseif (isset($_GET['teamid'])) include('teamid.php');
elseif (isset($_GET['serverid'])) include('serverid.php');
elseif (isset($_GET['awardid'])) include('awardid.php');
elseif (isset($_GET['galleryid'])) include('galleryid.php');
elseif (isset($_GET['threadid'])) include('threadid.php');
elseif (isset($_GET['blogid'])) include('blogid.php');
..
elseif (in_array($_GET['content'], $pages)) include($_GET['content']);
else echo "File not found =(";
could i somehow add the identifiers to the array too? but i want the pages as index.php?matchid=9438 and for regular pages: index.php?content=matches
would really aprricate some ideas
thanks!
My Suggestion, From My Comment is this:
In order to check what type of id it is, you should use two $_GET parameters. One is the type (match, award, server, etc), one is the ID. That way you don't have to check for 500 different $_GET parameters, just the value of 2. Much more standardized.
Second, you want to make all of it under 1 file for the ID showing.
In the spirit of writing less code, not more, it would be relatively easy to change the SQL statement to grab the record based on if $_GET['type'] was match, award, team, etc. This is of course given that they will probably look the same. If they don't, instead of writing new code to grab each type, instead write code to display it differently
All Variables in this code much be validated/sanatized beforehand.
// First Get the Type
$type = $_GET['type'];
// Then the ID
$id = $_GET['id'];
// SANITIZE YOUR DATA. Replace this with your sanitization.
die("SANITIZE YOUR DATA HERE");
// Get Data Here
$sql = "SELECT * FROM table WHERE type=".$type." AND id=".$id;
$data = mysql_query($sql);
// Next, Include a template based on the data.
// Global the variable so it can be used in the file
Global $data;
include($type."-template.php");
I agree with Tom -- you should look into using a framework such as Zend, Cake, Symfony, Kohana, CodeIgniter, ez-Components, or Seagull. The advantage of using a framework is that they have already solved a lot of issues for you, including:
1) How to structure your code
2) How to interpret pretty urls (i.e. /x/1/y/2 instead of ?x=1&y=2)
3) Where to put certain types of code (html, php, configs, etc)
4) How to fix something you can't figure out (because these frameworks have communities)
and much much more...
That being said, maybe you don't want all the overhead of using a framework (it does require you to learn a lot). In that case, I recommend Rasmus Lerdorf's "No Framework PHP Framework". Rasmus is the creator of PHP, so you know he knows his stuff.
Lastly, to answer your actual question, here's how I would do it:
could i somehow add the identifiers to the array too?
i want the pages as index.php?matchid=9438
and for regular pages: index.php?content=matches
Sure, but yes, as Chacha102 said, you will need 2 parameters: $area (page) and $id.
Example: index.php?area=articles&id=2345
Then you can re-organize & simplify your 'front controller' this way:
/index.php
/areas/articles.php
/areas/boards.php
etc.
Instead of naming the templates articleid.php, just call it articles.php -- this way your area name also tells you which template to use.
$valid_areas = array("matches", "boards", "search", "articles",
"interviews", "userlist", "teams", "servers",
"awards", "gallery", "qids");
$area = strtolower(trim($_REQUEST['area'])); //if you are not posting any forms, use $_GET instead
$id = (int)$_REQUEST['id']; //if you are not posting any forms, use $_GET instead
if(!$id)
{
include('home_en.php');
}
if(!in_array($area), $valid_areas))
{
echo 'Sorry, the area you have requested does not exist: '.$area;
exit();
}
else
{
$template = '/templates/'.$area.'.php';
if(!file_exists($template))
{
echo 'Sorry, the file you have requested does not exist: '.$area.' '.$id);
}
else
{
include($template);
}
}
It might help to go ahead and use a framework such as Zend:
http://framework.zend.com/
You could do this:
<?php
$controllerDefault = 'home';
function sanitize($str)
{
return str_replace(array('.', '/', '\\'), '', $str);
}
//Prevent of Remote File Inclusion
$controller = sanitize($_GET['controller']);
$id = intval($_GET['id']);
if (empty($controller))
{
$controller = $controllerDefault;
}
if (!empty($id))
{
$controller .= 'id';
}
$controllerFile = $controller . '.php';
if (!file_exists($controllerFile)
|| $controller == 'index') //for not recursive index.php include :)
{
exit('Controller "'.$controllerFile.'" not exists');
}
include($controllerFile);
?>
Using this code you can use your application like:
http://yoursite.com/index.php //include('home.php')
http://yoursite.com/index.php?id=285230 //include('homeid.php')
http://yoursite.com/index.php?controller=matches //include('matches.php')
http://yoursite.com/index.php?controller=matches&id=28410 //include('matchesid.php')
http://yoursite.com/index.php?controller=notexists //ERROR! Controller "notexists" not exists
http://yoursite.com/index.php?controller=../../etc/passwd //ERROR! Controller "etcpasswd" not exists
I hope you like it
PD: the code is not tested, but I hope you catch my idea