How can I add records on an empty table - php

I have an empty table in my database in MySQL, and I trying to add multiple records
(I do this in this way because I'm following and order; If I delete a record then the auto increment field (id) skips 1 value. For example. I delete the id = 340 and then the following record start with an id with a value = 341)
I have an If Else statement in a function in my controller where I use to compare the id itself of my table Hours.
public function showHours($id){
$complex = ComplexNew::find($id);
$fields = CourtsComplex::all();
$hours = HoursNew::all();
$last_hours = collect($hours)->last();
if ($last_hours->id == $last_hours->id){
$last_hours->id = $last_hours->id + 1;
}else{
return Redirect()->back();
}
return view('hours.FormNewHours')->with('complex', $complex)->with('fields', $fields)->with('last_hours', $last_hours);
}
And this line is the line where I have the error.
if ($last_hours->id == $last_hours->id){
//DO SOMETHING
// ...
}
The error is: 'Trying to get property 'id' of non-object'.
Also I was trying to add another if else statement something like this:
if(is_null($last_hours->id)){
$last_hours->id = 1;
}else if($last_hours->id == $last_hours->id){
//ADD +1 TO ID.
}
Because I want that if the table is empty the id of the first record must be started with value = 1 but if the table is not empty add 1 to the last id, like a for statement because this condition add always +1 to last id.

Change
$last_hours = collect($hours)->last();
to
$last_hours = $hours->last();
Plus dd($last_hours) if it returns object then try accessing id like $last_hours->id

Related

How to increment MAXIMUM value in laravel

I need to increment the revision no. (known as quot_rev, not a primary key as there is already record id) which is based on quot_id, so I need to get the maximum (highest) quot_rev value and then increment it when the user goes to the edit page, in which the user can save it as a new record.
public function edit($quot_id)
{$quotation = Quotation::where('quot_id', $quot_id)->orderBy('quot_rev', 'desc')->latest()->first();
if ($quotation->quot_rev > 0){
$quotation->max('quot_rev')+1;
}
return view('quotation.quotation_edit', compact('quotation', 'quot_rev'));
For the above code, laravel only show the max quot_rev no. but it didn't add 1 for me.
I have tried several ways like $quotation->increment(max('quot_rev')); and $quotation->max('quot_rev')++; but it all didn't work. Either it says error or it did not add 1.
Can anyone be able to help? I'm still a beginner at laravel. TIA.
you don't need to send quotation and quote_rev seperatly. you can get it from quotation objct
public function edit($quot_id)
{
$quotation = Quotation::where('quot_id', $quot_id)->orderBy('quot_rev', 'desc')->first(); // your query is duplicated, you can remove the latest(),
if ($quotation->quot_rev > 0){
$quotation->quot_rev = $quotation->quot_rev+1;
}else{
$quotation->quot_rev = 1;
}
//if you want to save it in database as welll
$quotation->save();
return view('quotation.quotation_edit', compact('quotation'));
}
You can try this
public function edit($quot_id)
{
$quotation = Quotation::where('quot_id', $quot_id)->orderBy('quot_rev', 'desc')->first(); // your query is duplicated, you can remove the latest(),
$maximum = 0;
if ($quotation->quot_rev > 0){
$maximum = $quotation->quot_rev+1;
}
return view('quotation.quotation_edit', compact('maximum'));
If you just need the next quot_rev, you can just pass the $maximum variable
Hope this helps.

How to update multiple rows using a single value in laravel?

I'm a beginner in laravel, I would like to update multiple rows using one input field.
My Database records:
For an instance, my input field has the value of 500, When I submit this field, it will then Update the multiple selected id from database from oldest to latest.
If the first row has the quantity of 100 it will be 500 - 100, and then it will proceed to the second row in which the value of input field is now 400 and it will again get the difference of the second row 400 - 200 until the input field becomes 0.
Is this possible? Thank you.
Run foreach and pass your input field inside it. Simple
You can follow below code for understanding ..
public function updateRecord(Request $req)
{
//get data from oldest(ASC) to latest (desc).
$var = $req->input_field;
$data = ModelName::orderBy('id','asc')->get();
foreach ($data as $key)
{
// ($var < 0) in case negative value
if($var == 0 || $var < 0)
{
break;
}
//find row with id
$singleRow = ModelName::find($key->id);
//holding data base quantity
$dummyHolder = $single->quantity_requested;
$single->quantity_requested = $dummyHolder + $var;
$singleRow->save();
//update variable
$var = $var - $dummyHolder;
}
}

SilverStripe unique URL (debug)

In this DataObject there is a user supplied field Title which has to be converted to a unique URL slug.
Desired Result: Duplicate URL's should get a suffix to its value. So saving 2 records with Title Foo should result in one record with foo as its value for column URL and the second record should have value foo-2 for the same column.
public function onBeforeWrite() {
parent::onBeforeWrite();
// Sanitize Title field to use for URL
$filter = URLSegmentFilter::create();
$this->URL = $filter->filter($this->Title);
// If URL is not unique, add suffix
$i = 1;
while($this->uniqueURL($this->URL)) {
$i++;
$this->URL = $this->URL . "-" . $i;
}
}
method: uniqueURL (within same class)
public function uniqueURL($URL) {
// Check if there is a record with the same URL
$existingURL = DataObject::get('NewsArticle', "URL = '$URL'");
if ($existingURL) {
// this is a duplicate URL
return false;
} else {
// this is a unique url
return true;
}
}
Saving Foo twice would result in foo and foo-2.
When saving two records with the same Title Foo results in two URL fields with foo
Why do you have two foo urls?
If you check your DB before inserting all records, this means that the check will not work on your record batch.
Don't use a loop to count unique urls
You don't need to loop and check every time and increment the count ($i). Performance wise youre far better off doing a COUNT() in a query and just use that value for your next insert.
// The following does exactly the same with just 1 query. No loop needed.
$count = DB::query("SELECT COUNT(*) FROM Table WHERE Title LIKE '{$filteredTitle}'")->value();
if ($count > 1) {
$filteredTitle .= "-" . $count;
}
$this->URL = $filteredTitle
Solutions
To do it onBeforeWrite() the only possibility is to Query your data AND check your records before they are saved.
Or a simpler solution with the same results is that you can change the url in an onAfterWrite() , and check use the amount of same titles as number.
public function onAfterWrite() {
parent::onAfterWrite();
// Sanitize Title field to use for URL
$filter = URLSegmentFilter::create();
$filteredTitle= $filter->filter($this->Title);
$count = DB::query("SELECT COUNT(*) FROM Table WHERE Title LIKE '{$filteredTitle}'")->value();
if ($count > 1) {
$filteredTitle .= "-" . $count;
}
$this->URL = $filteredTitle
}

PHP SQL Update array

I originally was satisfied with the following in order to update row 1 and row 2 to the same value (status=1)
if ($_POST){
$sql ="UPDATE table SET status = 1,
WHERE id IN (1,2 );";
db()->query($sql);
if(db()->query($sql)){
echo "<b>Good</b>";
}
else{
echo "<b>No Good</b>";
}
}
But now I want to update with different values, ie- row 1 to status 1, row 2 to status 2, and row 3 to status 3.
Off the bat, I know I need to
1. Use an array and loop through it three times.
2. pass in the array value into the $sql
I figure it would be something like this but I am still learning PHP..
$array_id = array(1, 2, 3);
$array_status = array(1, 2, 3);
if ($_POST){
$sql ="UPDATE table SET status = $array_status
WHERE id = $array_id;";
db()->query($sql);
if(db()->query($sql)){
echo "<b>Update Successful</b>";
}
else{
echo "<b>Update Unsuccessful</b>";
}
}
How would I go about making this happen?
You can loop through the arrays using a for loop and exec a query for each one (Radu Vlad answer), or you can build a long query and execute it once, something like this:
if ($_POST){
$sql = ""; // Blank string
$len = count($array_id); // Number of iterations
for ($i = 0; $i < $l; $i++) { // Enter the loop
$sql .= "UPDATE
table
SET
status = {$array_status[$i]}
WHERE id = {$array_id[$i]};"; // Append the query
}
db()->query($sql);
if(db()->query($sql)){
echo "<b>Update Successful</b>";
}
else{
echo "<b>Update Unsuccessful</b>";
}
}
When the val of $i is 0, then $array_id[$i] will print the first element, when $i is 1, $array_id[$i] will print the second element, and so on.
Using .= you append text to a string. By the end of the loop, $sql will be a string with 3 queries ('UPDATE ... SET ...; UPDATE ... SET ...; UPDATE ... SET ...;').
Not sure if it's the best way, though. But you get the idea.
If yow want the status to be equal to the id, do this (single query):
UPDATE table SET status=id WHERE id IN (1,2,3);
Of course you can use some math, like:
UPDATE table SET status=(id+1)*2 WHERE id IN (1,2,3);
You didn't really explain why you need that, so
try1(childish): set status = id
"UPDATE table SET status = id"
It's a bad practice, and only you could understand what those numbers are. Plus if id is auto-increment, status will be auto-increment too, you will have a duplicate column. If status has only 3 values posible, you should not do this.
try2(basic): do 3 updates, or actually, do as many as you need with a for
if ($_POST){
$status = 1;
for ($i = 1; $i <= 3; $i++){
$sql ="UPDATE table
SET status = $status
WHERE id = $i;";
db()->query($sql);
$status++;
}
A better way bacause you have more control over the status. Of course the second try is irrelevant if you have only that 3 values. This one assumes you will change the $status variable inside the for loop, in concordance with the $i (id)
try3(mature): set one or 2 arrays with the concordance between id and status, so that either $arr[$id] will have the value of status and the key will be the id, or $arr1[$i] will have the value of id, and $arr2[$i] will have the value of status
the example will have only one array(also called map, because you map a value based on another value)
if ($_POST){
$status_array = array(1 => 1,2 => 2,3 => 3);
for ($i = 1; $i <= 3; $i++){
$sql ="UPDATE table
SET status = $status_array[$i]
WHERE id = $i;";
db()->query($sql);
}
Also, this works because the array is consistent. If you do not have an consistent array you should either work with 2 arrays, or try a foreach with key->value instead of for
I would suggest you to use the following code:
$theArray = array("1" => "1","2" => "2","3" => "3"); // The scheme is ID => Status
$errorMsg = false; // Our default assumption is that no error occured
foreach($theArray as $key => $value) {
$sql = "UPDATE table SET status =".$value." WHERE id = ".$key;
if(!db() -> query($sql)) { // Execute the query and check whether it failed
$errorMsg = "Query for ID ".$key." failed.";
break; // When the query failed we exit the loop and echo the error message
}
}
if($errorMsg) { // If an error occured (errorMsg is no longer false) we echo it here
echo $errorMsg;
}
Basically you do just create one array $theArray, which contains key => value pairs of the IDs and the statuses you want to give them. Afterwards, you loop through this array, execute the db() -> query() for each key => value pair and check whether it failed or not. If a query failed, you break the loop and output the error message.
Advantages:
Instead of using two arrays ($array_id, $array_status) I do use only one associative array $theArray. The advantage here is that you only have one instead of two arrays and that you can extend the number of rows you'd like to change without changing your code. Just extend the array.
The array $theArray does not need to be in a chronological order and you can give each ID independently of the other IDs a status.
You are executing the db() -> query($sql) in your code two times. This is not very efficient and redundant. Instead you can execute the command only once and immediately check whether it failed or not based on its return value inside the if().
The errorMsg I am creating in the code let you know which query failed so it gives you a more detailed information for debugging.
If you want to update multiple rows (in single query) using the INSERT syntax, you can do this:
REPLACE table(id,status) VALUES(1,1),(2,2),(3,3)
Notice that id must be Primary Key or Unique, otherwise the REPLACE will insert a new row.
Notice also that REPLACE isn't SQL standard, and works only in MySQL.

PHP mySQL JOIN with matching column names

Noticed a rather large problem. When I join two tables togeter the fact that there is a column called ID in both of them causes the wrong tables ID to be used in a PHP equasion later on.
The simple solution would be to change the column name, but there are other standards thoughout the database too including columns called name in every table and title in many of them.
Is there a way around this or should I rename the entire database to ensure that there are no duplicate columns.
THE CODE FOR REFERENCE
$criteria = "SELECT *
FROM voting_intention,electors
WHERE voting_intention.elector = electors.ID
AND electors.postal_vote = 1
AND voting_intention.date = (select MAX(date)
from voting_intention vote2
where voting_intention.elector = vote2.elector)
AND electors.telephone > 0"
function get_elector_phone($criteria){
$the_elector = mysql_query("SELECT * $criteria"); while($row = mysql_fetch_array($the_elector)) {
return $row['ID']; }
While "Gunnx" solution is perfectly acceptable, I'd like to present an alternative since you appear to be using only the ID column of the result.
SELECT
electors.ID
FROM
voting_intention,electors
....
I wrote this function to assist in doing this. Basically it prepends the table name to the fields name of an associated array.
while($row = mysql_fetch_array($the_elector))
{
return $row['ID'];
}
would become
while($row = mysql_fetch_table_assoc($the_elector))
{
return $row['voting_intention.ID'];
}
function:
function mysql_fetch_table_assoc($resource)
{
// function to get all data from a query, without over-writing the same field
// by using the table name and the field name as the index
// get data first
$data=mysql_fetch_row($resource);
if(!$data) return $data; // end of data
// get field info
$fields=array();
$index=0;
$num_fields=mysql_num_fields($resource);
while($index<$num_fields)
{
$meta=mysql_fetch_field($resource, $index);
if(!$meta)
{
// if no field info then just use index number by default
$fields[$index]=$index;
}
else
{
$fields[$index]='';
// deal with field aliases - ie no table name ( SELECT T_1.a AS temp, 3 AS bob )
if(!empty($meta->table)) $fields[$index]=$meta->table.'.';
// deal with raw data - ie no field name ( SELECT 1, MAX(index) )
if(!empty($meta->name)) $fields[$index].=$meta->name; else $fields[$index].=$index;
}
$index++;
}
$assoc_data=array_combine($fields, $data);
return $assoc_data;
}
?>
mysql_fetch_row will get the data as a numerical array

Categories