How to Update a row if at least one field has changed - and return back all changes in laravel 5.7? - laravel-5

I am following this post in order to update a row if any field has changed.
//Retrieve an array from an API
$fields = ['field1'=>var1, 'field2'=>var2, ...];
$row = MyModel::ofField1($this->field1)->ofField2($fields['field2'])->first(); //Selects the row under field1 AND field2 condition. It is working.
$row->updateOrCreate($fields);//Should assign the new values to the model (but not persist)
//Next line should compare the model with what we have in the
//database. At least 1 value from the incomming array is different from what
//we have in the database - so Update the row with the new value.
if($row->isDirty()){
$row->save();
}
This is not working what I am missing?

->updateOrCreate() will persist the data (which you have mentioned you do not want to do).
This method has two arguments:
One to query rows with certain field values
The other for data to be used to update/create a record
In this case, if you are just checking if one of two fields have been updated, you should check if the specific field has been updated using ->isDirty($field):
$row = MyModel::first();
if ($row->isDirty('field1')) {
$row->field1 = $fields['field1'];
}
if ($row->isDirty('field2')) {
$row->field2 = $fields['field2'];
}
$row->save();
As you may have many fields returned from the api, you could loop through and check:
$row = MyModel::first();
foreach ($fields as $field => $value) {
if ($row->isDirty($field)) {
$row->$field = $value;
}
}
$row->save();

Related

Allow laravel to filter requests based on field types

So i have 300 different fields in my form generating from a database.These fields can be either a drop-down or text field which need to be saved in two different databases.
To get all the fields that are dropdown i will have to use
$request->input('name')
$request->input('email')
$request->input('username')
and 100 other fields.
rather than doing that and to filter requests based on input types
if(input_type==text){
save to this table
}
else if (input type==select){
save to this table
}
User laravel DB class for that.
Consider below example .
$data = array();
if(input_type==text){
$data['field1'] = 'somevalue';
}
else if (input type==select){
$data['field2'] = 'somevalue';
}
$Insert = DB::table('TABLE_NAME')->insert($data);
Make sure that table have detault value for fields which you are not inserting.
You can use something like this. I am guessing you have two different Model class for store in the database
$firstTableFields = [ 'field1', 'field2', 'field3'];
$secondTableFields = [ 'field4', 'field5', 'field6'];
$firstModel = new Model($request->only($firstTableFields));
$firstModel->save();
$secondModel = new Model($request->only($secondTableFields));
$secondModel->save();

How to concatenate an auto increment value before inserting into database in laravel

In my table I have a field that needs to be the same value as the id field which is auto increment and then the value is concatenated with certain strings.
How do I do this in store function of my controller?
I'm thinking of doing update right after insertion but I don't know how to get the inserted id, and that might be a problem if two or more users doing the same insertion into database at the same time.
Thanks
UPDATE:
in my store controller:
public function store(Request $request)
{
$kartukeluarga = new kartukeluarga();
$kartukeluarga->nomorkk = $request->input("nomorkk");
$kartukeluarga->kepalakeluarga = $request->input("kepalakeluarga");
$kartukeluarga->alamat = $request->input("alamat");
$kartukeluarga->save();
return redirect()->route('kk.index')->with('message', 'Item created successfully.');
}
the new field I want to add is 'rekamMedik' which doesn't need an input form but automatically concatenate the id and this string "kk-value of the id"
You can save details and then update that column.
If you have model Test.
$test = new Test();
$test->column_1 = "abc";
$test->column_2 = "def";
$test->column_x = ""; // Set Empty to the column where you will save id later
$test->save();
$test->column_x = "string".$test->id;
$test->save();
This might work.

Retrieving records from database using eloquent with optional query parameters

i have the following block of code in my Resource Controller:
$travel_company_id = Input::get('travel_company_id');
$transport_type = Input::get('transport_type');
$route_type = Input::get('route_type');
$travelRoutes = TravelRoute::where('travel_company_id', $travel_company_id)
->where('transport_type', $transport_type)
->where('route_type', $route_type)
->get();
Now what this does is it gets travelRoutes based on the parameters supplied. What i want is for it to do is perform a search based on the available parameters, that way if $route_type is empty the search will be performed only on travel_company_id and transport type.
Also if all the parameters are empty then it will simply do a get and return all available records.
I know i can do this with lots of if statements but then if i add a new parameter on the frontend i will have to add it to the backend as well, I was wondering if there was a much simpler and shorter way to do this in laravel.
The where method accepts an array of constraints:
$constraints = array_only(Input::all(), [
'travel_company_id',
'transport_type',
'route_type',
]);
$routes = TravelRoute::where($constraints)->get();
Warning: do not use Input::only() instead of array_only(). They're not the same.
Input::only() fills in any missing items with null, which is not what you want here.
This is pretty hacky and if you spend some time developing a solution I'm sure it could be much nicer. This assumes all the fields in the getSearchFields() function match the input names from the form and database.
/**
* Search fields to retrieve and search the database with. Assumed they match the
* column names in the database
*/
private function getSearchFields()
{
return ['travel_company_id', 'transport_type', 'route_type'];
}
public function search()
{
// Get a new query instance from the model
$query = TravelRoute::query();
// Loop through the fields checking if they've been input, if they have add
// them to the query.
foreach($this->getSearchFields() as $field)
{
if (Input::has($field))
{
$query->where($field, Input::get($field));
}
}
// Finally execute the query
$travelRoutes = $query->get();
}

One to Many relation - how to implement push

I am trying to do an insert which will create a parent record for one table and then insert records that link back to the parent record into another.
In other words this: User completes Course information form, then completes a series of questions on the same page. On submission, the course information is inserted into its own table then questions are inserted into a separate one.
My Course model is this:
class CourseVerification extends Eloquent
{
public function courseverificationqanda()
{
return $this->hasMany('CourseVerificationQandA', 'id', 'verification_id');
}
My Question model is this:
class CourseVerificationQandA extends InnovedBaseModel
{
public function courseverification()
{
return $this->belongsTo('CourseVerification');
}
On form submission, my controller is doing this:
// create course verification record first
$veri = new CourseVerification;
$veri->verification_date = $input['verification_date'];
// create collection to store questions
$collection = new Illuminate\Database\Eloquent\Collection();
// loop through submitted questions and push them to the collection
for($i = 0; $i < count(Input::get('question_id')); $i++) {
$answer = new CourseVerificationQandA;
$answer->question_id = $input['question_id'][$i];
$answer->answer = $input['answer'][$i];
$answer->additional_notes = $input['additional_notes'][$i];
$collection->push($answer);
}
// add collection to quesetion relation
$veri->courseverificationqanda = $collection;
// insert both course record and questions
$veri->push();
The push method then errors and debugs the SQL command
insert into `CourseVerification`
(`verification_date`, `topic_id`, `course_id`, `verifier_id`,`iv_status`,
`verification_type`, `courseverificationqanda`, `created_by`)
values
(29/10/2014, 1294, 47, 1, 1, I, [{"question_id":"2","answer":"0","additional_notes":""},
{"question_id":"3","answer":"0","additional_notes":""},
{"question_id":"4","answer":"0","additional_notes":""}], 1)
As you can see, the assignment of the collection to $veri->courseverificationqanda is then getting treated as a table column in the SQL query when it is actually a relationship to the question table.
Any ideas?
You have a few mistakes there.
You don't assign collection to the relation. You need to load that relation (as a collection in this case) and push on it, then just save everything:
$veri = new CourseVerification;
$veri->verification_date = $input['verification_date'];
// Save the parent model before you can add its children
if ($veri->save())
{
// loop through submitted questions and push them to the collection
for($i = 0; $i < count(Input::get('question_id')); $i++) {
$answer = new CourseVerificationQandA;
// associate with the parent model
// explicitly
$answer->verification_id = $veri->getKey();
// or the eloquent way
// $answer->courseverification()->associate($veri);
$answer->question_id = $input['question_id'][$i];
$answer->answer = $input['answer'][$i];
$answer->additional_notes = $input['additional_notes'][$i];
$veri->courseverificationqanda->push($answer);
}
}
// save both course record and questions
$veri->push();
Another thing are your relations, which are both wrong:
// this is how it should look like
// CourseVerification
public function courseverificationqanda()
{
return $this->hasMany('CourseVerificationQandA', 'verification_id', 'id');
}
// QandA
public function courseverification()
{
return $this->belongsTo('CourseVerification', 'verification_id');
}
In firsts case you swapped the keys, so it would work but not the way it should.
In second case you didn't specify the foreign key at all, so Eloquent would look for courseverification_id in the table (method_name_id).

How can I check if an order with a given increment id already exists in magento?

I am new to Magento.
What's the proper way to check if an order with a given increment id already exists ?
The obvious way:
$order = Mage::getModel('sales/order')->loadByIncrementId($reservedOrderId);
if ($order) {
Mage::log('already have order with id ' . $reservedOrderId);
return $order;
}
does not work, because I get a new and empty model instance back.
What's the correct way in magento to see if I have no such model for that id ?
The most common approach I've seen in core code just load()s a model and checks if there was a primary key assigned. In your case this would look like the following - note the very slight adjustment to the logical condition ($object->getId() vs. $object):
$order = Mage::getModel('sales/order')->loadByIncrementId($reservedOrderId);
if ($order->getId()) {
Mage::log('already have order with id ' . $reservedOrderId);
return $order;
}
It's a simple mistake, but remember that a call to load data on a Magento data model will always return the object instance. It's only if there is a result from the storage backend that the object would be decorated with data and therefore a primary key.
In my experience there are two ways to do this:
if ($order->hasData()) {
// order already exists
}
or, by using a collection;
$collection = Mage::getModel('sales/order')->getCollection()->addFieldToFilter('increment_id', $reservedOrderId);
if ($collection->count()) {
// order already exists
}
In your case, probably best to use the first one.
There's multiple ways to approach this. First, since you know the increment ID to expect, you could check for it after you get your model back
$increment_id = '100000002';
$order = Mage::getModel('sales/order')->loadByIncrementId($increment_id);
if($order->getIncrementId() == $increment_id)
{
var_dump("Increment IDs match, that means there's an order");
}
else
{
var_dump("Increment IDs don't match, that means there's no order");
}
Similarly, although there's a model returned even if there's no match, you could check that model's data — an empty array means nothing was loaded
$increment_id = '100000002';
$order = Mage::getModel('sales/order')->loadByIncrementId($increment_id);
if($order->getData())
{
var_dump("Data array means there's an order");
}
else
{
var_dump("Empty data array means there's no order");
}
Finally, you can load a collection with an increment id filter, and check how many items it contains
$increment_id = '100000002';
$c = Mage::getModel('sales/order')->getCollection()
->addFieldToFilter('increment_id',$increment_id);
if(count($c) > 0)
{
var_dump("A collection with more than zero items means the order exists");
}
else
{
var_dump("An empty collection means it does not");
}
I prefer the last approach for a simple "does/does-not" exists check, as a collection doesn't trigger a model's after load method which means it's theoretically more performant. That said, no approach is more valid than the other — just try to use the same technique everywhere for more readable code.

Resources