How to properly update a array that has only one identifying id - laravel

I'm trying to update an array with objects inside something like this, with the current code I have it only saves the first one, I know that's the problem but I don't know how to fix it
array (
0 =>
array (
'option' => 'new',
),
1 =>
array (
'option' => 'ewrwer',
),
),
This is my current code, the line in question is
$option = SurveyQuestionOption::where('survey_question_id', $preg->id)->first();
How do I fix this so it cycles through all in the array questionOptions instead of just the first one? I tried ->get() but then the ->save() doesn't work.
public function update(Request $request, $id)
{
DB::beginTransaction();
$preg = SurveyQuestion::findOrFail($id);
$preg->question = $request->question;
$preg->survey_section_id = $request->survey_section_id;
$preg->response_type_id = $request->response_type_id;
$preg->optional = $request->optional;
$preg->save();
$ids = [];
if ($request->get('questionOptions')) {
foreach ($request->get('questionOptions') as $item) {
$option = SurveyQuestionOption::where('survey_question_id', $preg->id)->first();
if (empty($option)) {
$option = new SurveyQuestionOption();
$option->survey_question_id = $preg->id;
}
$option->option = $item['option'];
$option->save();
}
}
if (count($ids) > 0) {
SurveyQuestionOption::whereNotIn('id', $ids)->where('survey_question_id', $preg->id)->delete();
}
DB::commit();
return back();
}

Basically, when you use get, you get a collection, so you can't really use save on it. you need to do a foreach loop, and save in that. i.e; like this;
$options = SurveyQuestionOption::where('survey_question_id', $preg->id)->get();
foreach($options as $option){
if (empty($option)) {
$option = new SurveyQuestionOption();
$option->survey_question_id = $preg->id;
}
$option->option = $item['option'];
$option->save();
}
Note that you can't save $options if you don't use a foreach loop, as you're not specifying which instance of the collection to save it in.

Related

Codeigniter count_all_results with having

I have composed a query using Codeigniter's Query Builder class. The query utilizes aliases and the having method. When I call the count_all_results method on this query, an exception occurs. Inspecting the log, I see that the query has stripped out the 'having' clauses. Is there a way to keep these clauses in while calling count_all_results? Thanks for your help.
EDIT: I first believed the problem was knowledge-based and not code-based and so did not share the code, but here it is. Please let me know if more is needed.
Here's the call on the model in the controller.
$where_array = array(
$parent_key.' is not NULL' => null
);
$search_post = $request_data['search'];
if (isset($request_data['filter'])) {
$filter_array = $request_data['filter'];
foreach ($filter_array as $filter_pair) {
if (isset($filter_pair['escape'])) {
$where_array[$filter_pair['filterBy']] = null;
} else {
if ($filter_pair['filterBy'] == 'table3_id') {
$where_array['table3.'.$filter_pair['filterBy']] = isset($filter_pair['filterId']) ?
$filter_pair['filterId'] : null;
} else {
$where_array[$table.'.'.$filter_pair['filterBy']] = isset($filter_pair['filterId']) ?
$filter_pair['filterId'] : null;
}
}
}
}
$like_array = array();
foreach ($request_data['columns'] as $key => $column) {
if (!empty($column['search']['value'])) {
$like_array[$column['data']] = $column['search']['value'];
}
}
$totalFiltered = $this->$model_name->modelSearchCount($search, $where_array, $like_array);
Here's the model methods.
public function modelSearchCount($search, $where_array = null, $like_array = null)
{
$this->joinLookups(null, $search);
if ($where_array) {
$this->db->where($where_array);
}
if ($like_array) {
foreach($like_array as $key => $value) {
$this->db->having($key." LIKE '%". $value. "%'");
}
}
return $this->db->from($this->table)->count_all_results();
}
protected function joinLookups($display_config = null, $search = null)
{
$select_array = null;
$join_array = array();
$search_column_array = $search ? array() : null;
$i = 'a';
$config = $display_config ? $display_config : $this->getIndexConfig();
foreach ($config as $column) {
if (array_key_exists($column['field'], $this->lookups)) {
$guest_model_name = $this->lookups[$column['field']];
$this->load->model($guest_model_name);
$join_string =$this->table.'.'.$column['field'].'='.$i.'.'.
$this->$guest_model_name->getKey();
$guest_display = $this->$guest_model_name->getDisplay();
if ($search) {
$search_column_array[] = $i.'.'.$guest_display;
}
$join_array[$this->$guest_model_name->getTable().' as '.$i] = $join_string;
$select_array[] = $i.'.'.
$guest_display;
} else {
$select_array[] = $this->table.'.'.$column['field'];
if ($search) {
$search_column_array[] = $this->table.'.'.$column['field'];
}
}
$i++;
}
$select_array[] = $this->table.'.'.$this->key;
foreach ($join_array as $key => $value) {
$this->db->join($key, $value, 'LEFT');
}
$this->db->join('table2', $this->table.'.table2_id=table2.table2_id', 'LEFT')
->join('table3', 'table2.table3_id=table3.table3_id', 'LEFT')
->join('table4', $this->table.'.table4_id=table4_id', 'LEFT')
->join('table5', 'table4.table5_id=table5.table5_id', 'LEFT');
$this->db->select(implode($select_array, ', '));
if ($search) {
foreach (explode(' ', $search) as $term) {
$this->db->group_start();
$this->db->or_like($this->table.'.'.$this->key, $term);
foreach ($search_column_array as $search_column) {
$this->db->or_like($search_column, $term);
}
$this->db->group_end();
}
}
$this->db->select('table2_date, '. $this->table.'.table2_id, table4_id, '. 'table5.table5_description');
}
Since count_all_results() will basically run a Select count(*) and not count the rows in your resultset (basically rendering the query useless for your purposes) you may use other Codeigniter methods to get the resultset and the row count.
Try running the query into a variable:
$query = $this->db->get();
From then, you can do pretty much anything. Besides returning the result with $query->result(); you can get the number of rows into another variable with:
$rownum = $query->num_rows();
You can then return that into your controller or even just return the $query object and then run the num_rows() method on the controller
To answer this question, count_all_results() transforms the original query by replacing your selects with SELECT COUNT(*) FROM table. the aliased column would not be selected, and the having clause would not recognize the column. This is why count_all_results() does not work with having.

error while update method on boolean

I am trying to update method in Laravel but error is:
"Call to a member function tradereason() on boolean"
I also check same question of other people asked but there're a lot of different in my process. I have lot tables.
let me show you my create code and update method coding.
Create method code:
public function store(Request $request)
{
$tradeID= Auth::user()->trade()->create($input);
$input = $request->all();
$reasons = $request->input('reason');
//Loop for creating KEY as Value
$data = [];
foreach($reasons as $key => $value) {
$data[] = ['reason_id' => $value];
};
if( $data > 0 ) {
foreach ($data as $datum) {
$tradeID->tradereason()->save(new TradeReason($datum));
}
}
}
this is my tring code for update method:
public function update(Request $request, $id)
{
$tradeID= Auth::user()->trade()->whereId($id)->first()->update($input);
$input = $request->all();
$reasons = TradeReason::whereId($id)->first();
$reasons->update($input);
$reasons->tradereason()->sync($request->input('reason'));
$data = [];
foreach($reasons as $key => $value) {
$data[] = ['reason_id' => $value];
};
if( $data > 0 ) {
foreach ($data as $datum) {
$tradeID->tradereason()->whereId($id)->first()->update($datum);
}
}
}
update returns a boolean. So, don't overwrite $tradeID with the results of update.
$tradeID = Auth::user()->trade()->whereId($id)->first();
$tradeID->update($input);
Calling update on the Builder returns an 'int'. Calling update on the Model returns a 'bool'. They don't return Model instances.
// bool
$tradeID= Auth::user()->trade()->whereId($id)->first()->update($input);
The model instance would be what is returned from the first call:
$tradeID = Auth::user()->trade()->whereId($id)->first(); // assuming it finds a record
You can update that, you can use it in the foreach loop.

Laravel controller, move creating and updating to model?

my question is about how to split this code. I have a registration form and it's saving function looks like this:
public function store(EntityRequestCreate $request)
{
$geoloc = new Geoloc;
$geoloc->lat = $request->input('lat');
$geoloc->lng = $request->input('lng');
$geoloc->slug = $request->input('name');
$geoloc->save();
$user_id = Auth::id();
$entity = new Entity;
$entity->name = $request->input('name');
$entity->type = $request->input('type');
$entity->email = $request->input('email');
$entity->tags = $request->input('tags');
$entity->_geoloc()->associate($geoloc);
$entity->save();
$entity_id = $entity->id;
$address = new Address;
$address->building_name = $request->input('building_name');
$address->address = $request->input('address');
$address->town = $request->input('town');
$address->postcode = $request->input('postcode');
$address->telephone = $request->input('telephone');
$address->entity_id = $entity_id;
$address->save();
$role = User::find($user_id);
$role->role = "2";
$role->save();
DB::table('entity_user')->insert(array('entity_id' => $entity_id, 'user_id' => $user_id));
$result = $geoloc->save();
$result2 = $entity->save();
$result3 = $address->save();
$result4 = $role->save();
if ($result && $result2 && $result3 && $result4) {
$data = $entity_id;
}
else {
$data = 'error';
}
return redirect('profile/entity');
}
As you see, it has a custom request and it is saving to 3 models, that way my controller code is far too long (having many other functions etc) Instead I want to move this code to a model, as my model so far has only relationships defined in it. However I don't exactly know how to call a model from controller, do I have to call it or it will do it automatically? Any other ideas on how to split the code?
You could use the models create method to make this code shorter and more readable.
For example:
$geoloc = Geoloc::create(
$request->only(['lat', 'lng', 'name'])
);
$entity = Entity::create(
$request->only(['name', 'type', 'email', 'tags])
);
$entity->_geoloc()->associate($geoloc);
$address = Address::create([
array_merge(
['entity_id' => $entity->id],
$request->only(['building_address', 'address', 'town'])
)
])
...
The create method will create an object from a given associated array. The only method on the request object will return an associated array with only the fields for the given keys.

Using with() and find() while limiting columns with find cancels relation data

I have the following code that displays different data depending on if you are the authenticated user looking at your own data or if you are looking at data from another user. The code works but in my opinion is very nasty.
public function showUserDetailed(Request $request, $username)
{
$key = strtolower($username).'-data-detailed';
if(Auth::user()->usenrame === $username) {
$key = $key .'-own';
}
if(Cache::has($key)) {
if($request->wantsJson()) {
return request()->json(Cache::get($key));
} else {
return view('user/detailed', ['user' => Cache::get($key)]);
}
} else {
if(Auth::user()->username === $username) {
$u = User::where('username', $username)->first();
$user = new \stdClass();
$user->username = $u->username;
$user->email = $u->email;
$user->address = $u->address;
$user->city = $u->city;
$user->state = $u->state;
$user->zip = $u->zip;
$user->phone = $u->phone;
$user->follows = $u->follows;
$user->ratings = $u->ratings;
$user->location = $u->location;
} else {
$u = User::where('username', $username)->first(['username', 'city', 'state']);
$user = new \stdClass();
$user->username = $u->username;
$user->city = $u->city;
$user->state = $u->state;
$user->follows = $u->follows;
$user->ratings = $u->ratings;
}
Cache::put($key, $user);
if($request->wantsJson()) {
return response()->json($user);
} else {
return view('user/detailed', ['user' => $user]);
}
}
}
I have tried to use something similar to the following in the model calls.
User::where('username', $username)->with('follows', 'ratings', 'location')->find(['username', 'city', 'state');
However when I specify the columns to get from the user table it negates the relation data so it comes back as empty arrays. Is there a different way I can do this which would be cleaner? I despise having to create a stdClass to be a data container in this situation and feel I may be missing something.
// this works
User::where('username', $username)->with('follows', 'ratings', 'location')->first();
// this also works
User::where('username', $username)->first(['username', 'city', 'state']);
// this does not
User::where('username', $username)->with('follows', 'ratings', 'location')->first(['username', 'city', 'state']);
When you specify columns and want to get the related models as well, you need to include id (or whatever foreign key you're using) in the selected columns.
The relationships execute another query like this:
SELECT 'stuff' FROM 'table' WHERE 'foreign_key' = ($parentsId)
So it needs to know the id of the parent (original model). Same logic applies to all relationships in a bit different forms.

How to return the current inserted row data in Laravel?

I have inserted a row in db using laravel eloquent method. See the code below,
public function store() {
$language = new languages;
$language -> languages = Input::get('languages');
$language -> created_by = Auth::user()->id;
$language -> updated_by = Auth::user()->id;
if( $language -> save() ) {
$returnData = languages::where("id","=",$language -> id) -> get();
$data = array ("message" => 'Language added successfully',"data" => $returnData );
$response = Response::json($data,200);
return $response;
}
}
I want the last inserted row from the table, but my response contains empty data. Please guide the right method of getting the data?
Almost there: you would need to call first() to get just one row. But, since you're using eloquent, you can call the find() method:
public function store() {
$language = new languages;
$language->languages = Input::get('languages');
$language->created_by = Auth::user()->id;
$language->updated_by = Auth::user()->id;
if($language->save()) {
$returnData = $language->find($language->id);
$data = array ("message" => 'Language added successfully',"data" => $returnData );
$response = Response::json($data,200);
return $response;
}
}

Resources