Best way to add multiple notes to a database with php dynamically - php

I currently have a website which should be able to take notes from user input and save them into the database. I'm looking for some guidance on the best way to achieve this.
The website should only show the most recent notes that were added, but all other notes should still be saved(but hidden). I don't know how many times the user will enter notes. My initial thought was to dynamically add a column to the database each time the user enters notes, but then I'd end up having a new column for every notes entry.Its worth mentioning that the notes are associated with a filename, so there may be many rows in the database that will all have different notes.
The dbforge method was the way I was going to go about it but that will repeatedly try to add 'notes' to the database (which will already exist after one go).
$fields = array(
('notes') => array('type' => 'TEXT','constraints' =>'255')
);
$this->dbforge->add_column('mytable', $fields);
Would anyone know a better way of doing this? I'm using php and the codeigniter framework.
All help is much appreciated!

I would have a notes table which stores User Id, Note and Date Added.
In your view, your form will point to this in your controller:
public function addNote($user_id)
{
$this->form_validation->set_rules('note', 'Note', 'required');
if ($this->form_validation->run() == true) {
$array = array (
'user_id' => $user_id,
'note' => $this->input->post('note')
);
$this->your_model->addRecord('notes', $array);
}
}
The addRecord() function in your model would look like:
public function addRecord($table, $array)
{
$this->db ->insert($table, $array);
return $this->db->insert_id();
}
You can then do a query like this and pass the results back to your view:
public function getLatestNoteByUser($user_id)
{
$this->db->select('id, note')
->from('notes')
->where('note_added_by', $user_id)
->order_by('date_added', desc)
->limit(1);
return $this->db->get()->row();
}
This will return only the last note added by a specified user. You could set the limit to whatever value you want and return row_array() instead of row(). You could even pass $limit, in the functions parameters and use ->limit($limit).

Related

Laravel mySQL view return by specific ID

So I am quite new to Laravel, and I have a situation, where I am trying to gather data from a pivot table (contains 2 foreign keys only) in order to retrieve data from other tables.
Before everything, I'd like to note, that word "campaign" is the same as "box". Simply it differs in database and front.
I have multiple boxes, that contains specific gifts.
I have set the URL of the box to be something as such: http://127.0.0.1:8000/box/1
http://127.0.0.1:8000/box/2
etc..
I have done so, by simply using a button with the {id}:
View the box
My plan is, to print out only that specific boxes gifts (right now, all boxes print out all gifts).
I have tried to use the ->where option within my function, although, it seems that I can't try equaling to the campaigns ID.
Incorrect code:
function box(){
$data = array(
'list'=>DB::table('campaigns_gifts')
->join('gift_items', 'gift_items.id', '=', 'campaigns_gifts.gift_foreignK')
->select('gift_items.*')
->where($campaign_foreignK = '{id}')
->get()
);
return view('DBqueries.boxView', $data);
}
My question is, how can I specifically return data, that only belongs to that specific box, since I am not able to use mysql where option.
For reference, these are the database tables:
Basically, I would need to match my URL's id with campaign_foreignK
Thank you in advance.
First of all, yout need to start to use Laravel Eloquent Models.
But doing by your way (the hardest):
You need to create a route in web or api, something like that:
Route::get('/box/{id}', [BoxController::class, 'view']);
Then you need to put this function on your controller:
function view($id){
/**
* You can do it by 2 ways:
* 1 - Do a where in the result of DB query (the bad way)
*/
$list = DB::table('campaigns_gifts')
->join('gift_items', 'gift_items.id', '=', 'campaigns_gifts.gift_foreignK')
->select('gift_items.*')
->where($campaign_foreignK = '{id}')
->get();
$list = (array)collect($list)->where('abc', 123);
/**
* Or the second way (the best is to use the Eloquent, but using DB the following is the best)
* 1 - Get the relations:
* Is git_items id the key for gift_foreignK ? i'm supposing that is it! so....
*/
$giftsIds = array_values((array)DB::select("select * from campaigns_gifts where campaign_foreignK = $id"));
$giftsIdsString = implode($giftsIds, ',');
$list = (array)DB::select("select * from gift_items where id in ($giftsIdsString)");
return view('DBqueries.boxView', ['list' => $list]);
}

How to unserialize field before compare by andFilterWhere(['like', ...)

In yii2 I have model with search:
public function search($params)
{
$query = MyModel::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}
$query->andFilterWhere(['like', 'passengers', $this->passengers]);
return $dataProvider;
}
passengers is a TEXT field in mysql table that contains serialized array.
Q: How to tell andFilterWhere() function make unserialize and compare by any element from array? Something like this: $query->andFilterWhere(['like', unserialize('passengers')[0]['name'], $this->passengers]); - means first element of array with 'name' key
Unfortunately this is a gotchya in your data structure. Storing serialized data makes it much more difficult to query. The andFilterWhere method only produces SQL level filtering, and you really need code-level filtering as SQL has no idea what PHP Serialization is. There are two ways you could go about solving this:
Post Query Filter
Depending on how large your table is, you could return all results of the search query and then use a simple loop to deserialize and drop out values that aren't in your passenger list.
Pseudo code would be:
$result = MyModel::search(...);
$filteredResult = array_filter($result->toArray(), function ($el) {
$availablePassengers = unserialize($el['passengers']);
return count(array_intersect($availablePassengers, $this->passengers));
});
Change Your Structure
Probably the best solution would be to change your data structure so passengers are stored in a many-to-many relationship. This would allow you to perform this kind of filtering with a database query and would keep your data properly normalized.

SQL Sum on single field with cakePHP don't work with paginate()

I need to get the sum of the field "valor", from the table "orcamentos".
I'm using this and it is working, but I know that this is not the right way:
//function index() from OrcamentosController.php
$orcamentoSubprojetosTotal = $this->Orcamento->query(
"SELECT
SUM(Orcamento.valor) AS TotalOrcamentoSuprojetos
FROM
orcamentos AS Orcamento
WHERE
Orcamento.subprojeto_id IS NOT NULL;"
);
$this->set(compact('orcamentoSubprojetosTotal'));
I have found this question cakephp sum() on single field (and others sum() function in cakephp query, using virtual fields to sum values in cakephp), but in the moment I add this line to my controller:
$this->Orcamento->virtualFields['total'] = 'SUM(Orcamento.valor)';
The paginate() stops working and display only one entry, like so:
Page 1 of 1, showing 1 records out of 2 total, starting on record 1, ending on 2
This is my index() function:
public function index($tipoOrcamento = null) {
$this->Orcamento->recursive = 0;
/*
$orcamentoSubprojetosTotal = $this->Orcamento->query(
"SELECT
SUM(Orcamento.valor) AS TotalOrcamentoSuprojetos
FROM
orcamentos AS Orcamento
WHERE
Orcamento.subprojeto_id IS NOT NULL;"
);
$this->set(compact('orcamentoSubprojetosTotal'));
*/
$this->set(compact('tipoOrcamento'));
if($tipoOrcamento == 'subtitulo'){
$this->set('orcamentos', $this->Paginator->paginate('Orcamento', array('Orcamento.subtitulo_id IS NOT NULL')));
}elseif($tipoOrcamento == 'subprojeto'){
$this->set('orcamentos', $this->Paginator->paginate('Orcamento', array('Orcamento.subprojeto_id IS NOT NULL')));
}else{
$this->set('orcamentos', $this->Paginator->paginate('Orcamento'));
}
}
Can I use the query() or someone can help me with the virtual field?
Thank you.
Do not use a virtual field
A virtual field is intended for things like:
public $virtualFields = array(
'name' => 'CONCAT(User.first_name, " ", User.last_name)'
);
If a virtual field is used from something which does not belong to the/a single row - it will not do what you're expecting as evident by the secondary effects on the find call paginate generates.
Use field
Instead, use the field method and pass in the expression:
$integer = $Model->field(
'SUM(valor)',
array('NOT' => array('subprojeto_id' => null))
);
Which will execute:
SELECT SUM(valor) from x where NOT (subprojecto_id IS NULL);
This will also return a scalar value, whereas calling query as shown in the question will return a nested array.
of course when you use SUM you'll get a single record
there are two things you can do:
create the virtualField just before the find() call and unset it just after the query.
using 'fields' => arra(...) in your paginator setting and list just the fields you need to retrieve and not the virtualField when you don't want to SUM

CakePHP add model name to information returned in queries

I want to include the model name in the returned results of a query using CakePHP's find() methods.
For instance, if I do a
$person = $this->Person->find("first", array(
"conditions" => array (
"Person.id" => $id
)
));
I get back
Person{id:1, name:Abraham Lincoln}
I want to get back
Person{id:1, name:Abraham Lincoln, model: Person}
I'm fairly front-end oriented. I know I could loop through results and add these at the controller level, but that seems tedious, especially since most of my queries are far more complex, utilizing contain(). I imagine somewhere in CakePHP's core there's a place this kind of functionality could be added, I just don't know where.
Essentially, I'm looking for where CakePHP casts the database query to a php variable, so I can inject my additional model value.
I do know I will never use the column name "model" anywhere in my application. I'm also certain I want this information where I'm requesting it to be in every singe query, as little sense as it may make.
Add this to every model where you need it:
public function afterFind($results, $primary = false) {
foreach($results as $ikey => $item) {
foreach($item as $skey => $subitem) {
if(is_array($subitem))
$results[$ikey][$skey]['model'] = $skey;
else $results[$ikey]['model'] = $skey;
}
}
return $results;
}
Unfortunately I wasn't able to get this work when I stored it in AppModel.

grabbing the last last id based on user_name - codeigniter

I'm working on a project that has one main article and you can attach many different articles to it. So on submit I have broken the article from into two different sections, since I need them to submit into two different tables.
After submitting the first part, I'm trying to get the last submitted id based on their user_name so I can attach the rest of the article. If that makes sense.
I've tried several different things, but nothing seems to grab back that id.
First I tried the insert_id() meathod, but that returns a 0
public function pullLastStoryId($author){
$this->db->where('author', $author);
$this->db->insert_id();
$story = $this->db->get('story_tbl');
return $story->result();
}
So then I also tried just grabbing
public function pullLastStoryId($author){
$story = $this->db->query('SELECT LAST_INSERT_ID() INTO story_tbl;')
return $story->result();
}
Any idea's
My guess is that you are talking about a foreign-key relationship between two tables. One way to do this would be something like:
$this->db->insert('author',$vals);
$id = $this->db->insert_id();
// do something with ID.
From what I can tell, you would probably then do something like this:
$story_row = $this->db->get_where('story_tbl',array('id' => $id));
You should not have to worry about different user_name property, because that will be last created ID. If you really wanted to get that row back, though, you could do this:
$author_row = $this->db->get_where('author',array('author_id' => $id));
If you need to have this ID somewhere else (say, after another form is submitted), you can either use a hidden form input or (this is a bit more secure), you can store that ID in session.
I am not clear with the question. Are you looking for something like this?
public function pullLastStoryId(){
$story = $this->db->query('SELECT id from tablename where id = LAST_INSERT_ID()')
return $story->result();
}
OR
public function pullLastStoryId(){
$id = $this->db->insert_id();
$this->db->where('id',$id);
$story = $this->db->get('story_tbl');
return $story->result();
}
If you want to get Last id, your way is wrong. $this->db->insert_id() or etc for active query. Try this: SELECT id FROM table ORDER BY id DESC LIMIT 1

Categories