Zend Framework Database Insert Issue - php

I'm starting out using the Zend Framework and have created a suitable model which saves data back to a database table. The issue I am having is that the sql statement is trying to insert '?' as the value for each column in the database. I have created the following save function which passes an array of data to the DBtable adapter functions:
public function save() {
$data = $this->getData();
if ($data['pageId']==0) {
$this->getDbTable()->insert($data);
} else {
$this->getDbTable()->update($data, array('pageId = ?' => $data['pageId']));
}
}
This seems to go through the appropriate motions but the item is not added to the database and the sql statement within MySql logs looks something like:
insert into DB_Table ('pageId','title','body') values ('?', '?', '?');
Not quite sure where this is falling down, any pointers would be gratefully received.
Thanks

Data should be in next format:
$data = array(
'pageId' => 1,
'title' => 'title',
'body' => 'body'
);
Are you sure that $this->getDbTable() returns your db adapter?
Try to use:
$db = new Zend_Db_Table('table_name');
$db->insert($data);

Related

Array to string conversion error in Code Igniter when inserting array of data into table in database

I'm trying to insert an array of data into a table in database but an error said Array to string conversion error
This is the post function in my controller, first i post an array of data. The values of the array will be the names, and numbers, they are not id. The id is only kodejdwl. This will be pass to my model
function index_post() {
$data = array(
'kodejdwl' => $this->post('kodejdwl'),
'tahun_akad' => $this->post('kode_tahun_akad'),
'semester' => $this->post('semester'),
'mk' => $this->post('mk'),
'ruangan' => $this->post('ruangan'),
'nama_dosen' => $this->post('nama_dosen'),
'namakelas' => $this->post('nama_kelas'),
'jam_mulai' => $this->post('jam_mulai'),
'jam_selesai' => $this->post('jam_selesai'),
);
}
After the data from above code is passed to the model. I created some new variables which are the id of each the name of the value in the array data. e.g if the value of data['mk'] is Website then the id will be 1 and that id will be stored in variable $kodemk and i do it to each value in the data. Then i created new_data which stores array of the id's which i previously made. Then i insert that array into one table in my database. I thought it would be fine but it said Array to string conversion error. What should i do so i could insert that array into the table in my database?
public function insert($data){
$this->db->select('thn_akad_id');
$tahunakad_id = $this->db->get_where('tik.thn_akad',array('tahun_akad'=>$data['tahun_akad'],'semester_semester_nm'=>$data['semester']))->result();
$this->db->flush_cache();
$this->db->select('kodemk');
$kode_mk = $this->db->get_where('tik.matakuliah',array('namamk'=>$data['mk']))->result();
$this->db->flush_cache();
$ruangan = $this->db->get_where('tik.ruangan', array('namaruang' => $data['ruangan']), 1)->result();
$this->db->flush_cache();
$this->db->select('nip');
$nip_dosen = $this->db->get_where('tik.staff',array('nama'=>$data['nama_dosen']))->result();
$this->db->flush_cache();
$this->db->select('kodeklas');
$kodeklas = $this->db->get_where('tik.kelas',array('namaklas'=>$data['namakelas']))->result();
$this->db->flush_cache();
$this->db->select('kode_jam');
$kode_mk = $this->db->get_where('tik.wkt_kuliah',array('jam_mulai'=>$data['jam_mulai'],'jam_selesai'=>$data['jam_selesai']))->result();
$this->db->flush_cache();
$new_data = array(
'kodejdwl' => $data['kodejdwl'],
'thn_akad_thn_akad_id' => $tahunakad_id,
'matakuliah_kodemk' => $kode_mk,
'ruangan_namaruang' => $ruangan,
'staff_nip' => $nip_dosen,
'kelas_kodeklas' => $kodeklas,
);
$insert = $this->db->insert('tik.jadwal_kul', $new_data);
return $this->db->affected_rows();
}
You probably want to use row() instead of result() because it'll contain only one result that you want. If you want to use result() and store multiple values then you'll have to use implode to concatenate them and store it as a string.
I've written a possible solution for your problem; Some things were missing, so I've mentioned them in the comments. See if this helps you.
public function insert($data){
$this->db->select('thn_akad_id');
$tahunakad_id = $this->db->get_where('tik.thn_akad',array('tahun_akad'=>$data['tahun_akad'],'semester_semester_nm'=>$data['semester']))->row(); // use row here
$this->db->flush_cache();
$this->db->select('kodemk');
$kode_mk = $this->db->get_where('tik.matakuliah',array('namamk'=>$data['mk']))->row();
$this->db->flush_cache();
// remove your_ruangan_column with your desired column name
$this->db->select('your_ruangan_column');
$ruangan = $this->db->get_where('tik.ruangan', array('namaruang' => $data['ruangan']), 1)->row();
$this->db->flush_cache();
$this->db->select('nip');
$nip_dosen = $this->db->get_where('tik.staff',array('nama'=>$data['nama_dosen']))->row();
$this->db->flush_cache();
$this->db->select('kodeklas');
$kodeklas = $this->db->get_where('tik.kelas',array('namaklas'=>$data['namakelas']))->row();
$this->db->flush_cache();
// Not sure where this ↓↓ is being used but you can use it the same way as others
$this->db->select('kode_jam');
// duplicate variable name here ↓↓ (fix this)
$kode_mk = $this->db->get_where('tik.wkt_kuliah',array('jam_mulai'=>$data['jam_mulai'],'jam_selesai'=>$data['jam_selesai']))->row();
$this->db->flush_cache();
$new_data = array(
'kodejdwl' => $data['kodejdwl'],
'thn_akad_thn_akad_id' => $tahunakad_id->thn_akad_id, // {$tahunakad_id} consists an object with the key {thn_akad_id}-- table_column_name
'matakuliah_kodemk' => $kode_mk->kodemk, // ...
'ruangan_namaruang' => $ruangan->your_ruangan_column, // ...
'staff_nip' => $nip_dosen->nip, // ...
'kelas_kodeklas' => $kodeklas->kodeklas // ...
);
$insert = $this->db->insert('tik.jadwal_kul', $new_data);
return $this->db->affected_rows();
}
Your are making a total of 7 separate trips to the database. Best practice recommends that you always minimize your trips to the database for best performance. The truth is that your task can be performed in a single trip to the database so long as you set up the correct INSERT query with SELECT subqueries.
I don't know what your non-English words are, so I will use generalized terms in my demo (I've tested this successfully in my own CI project). I am also going to reduce the total subqueries to 3 to reduce the redundance in my snippet.
$value1 = $this->db->select('columnA')->where('cond1', $val1)->get_compiled_select('childTableA');
$value2 = $this->db->select('columnB')->where('cond2', $val2)->get_compiled_select('childTableB');
$value3 = $this->db->select('columnC')->where('cond3', $val3)->get_compiled_select('childTableC');
return (int)$this->$db->query(
"INSERT INTO parentTable
(column1, column2, column1)
VALUES (
($value1),
($value2),
($value3)
)"
);
// to mirror your affected rows return... 1 will be returned on successful insert, or 0 on failure
Granted this isn't using the ActiveRecord technique to form the complete INSERT query, but this is because CI doesn't allow subqueries in the VALUES portion (say, if you were to use the set() method). I am guessing this is because different databases use differing syntax to form these kinds of INSERTs -- I don't know.
The bottom line is, so long as you are fetching a single column value from a single row on each of these sub-SELECTs, this single query will run faster and with far less code bloat than running N number of individual queries. Because all of the variables involved are injected into the sql string using get_compiled_select() the stability/security integrity should be the same.

Codeigniter 3 model function no return variable

I'm making a project where a user can publish/post their own stories and read others' stories. Very simple.
This is my controller method named publish:
public function published()
{
$story = array('author' => $this->session->userdata('username'),
'title' => $this->input->post('title'),
'synopsis' => $this->input->post('synopsis'));
$new_storyid = $this->story_model->new_story($story);
if($new_storyid != NULL)
{
$genre = $this->input->post('genre');
for($temp=0;$temp<count($genre);$temp++)
{
$genres[$temp] = array('story_id' => $new_storyid,
'story_genre_name' => $genre[$temp]);
}
$insert_genre = $this->story_model->new_story_genre($genres);
$tag = $this->input->post('tags');
for($temp=0;$temp<count($tag);$temp++)
{
$tags[$temp] = array('story_id' => $new_storyid,
'story_tag_name' => $tag[$temp]);
}
$content_warning = $this->input->post('content_warning');
for($temp=0;$temp<count($content_warning);$temp++)
{
$content_warnings[$temp] = array('story_id' => $new_storyid,
'story_content_warning_name' => $content_warning[$temp]);
}
//$chapter = array('story_id' => $new_storyid,
//'chapter_number' => 1, 'chapter_title' => $this->input->post('chapter_title'),
//'chapter_content' => $this->input->post('chapter_content'),
//'chapter_number' => 1, 'date_added' => mdate('%Y-%m-%d %h-%i-%s',time()));
//$result = $this->story_model->add_chapter($chapter);
//if($result){
//redirect('account/userprofile_published_stories');}
}
}
This is my model methods for the above controller method:
public function new_story($story)
{
$this->db->select('user_id');
$query = $this->db->get_where('users',array('username' => $story['author']))->result();
foreach($query as $row)
{ $userid = $row->user_id; }
$publish = array('user_id' => $userid,
'story_title' => $story['title'],
'synopsis' => $story['synopsis']);
$this->db->insert('story',$publish);
return $this->db->insert_id();
}
public function new_story_genre($genre)
{
foreach($genre as $row)
{
$this->db->insert('story_genre', $row);}
}
public function add_chapter($chapter){
$this->db->where('story_id', $chapter['story_id']);
return $this->db->insert('chapters', $chapter);
}
I haven't added the other 2 functions for my tags and content warning inserts because i am confused right now. It all works fine, my genre is inserted.
My tables looks like this:
Story tables
In inserting a story in my above method, the first thing i do is insert a new story row in my story table and returns the new_storyid variable.
after that with the new storyid i add the genre,tags,content warning then the chapters.
My question is, what should i return in my methods for inserting the genre,tags,contentwarning?
I forgot this part because every model method ive written so far always returns a variable i needed in my controller. My first thought was to return a TRUE/FALSE variable if insert is successful/fail but barring special circumstances since ive already processed the data its 100% sure to insert successfully. Should i be returning TRUE/FALSE and adding an if statement like:
if($insert_genre){
//insert tags here
if($insert_tags){
//insert content warning here
if($insert_content_warning){
//insert chapters here
//redirect to view here
}
}
}
Or can i just not return anything? and if so, is this a proper/right way?
EDIT: I forgot to mention i haven't yet added form_validation rules before all the inserts. So my function will be nested in multiple if statements.
I just edited my model method:
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; }
}
Above compares the number of inserted rows with the number of rows passed into the method. Everytime a row is inserted it adds 1 to the inserted variable. So if my controller passes 3 rows into the method, the inserted variable should also be 3 for a successful insert.
I think you are correct in always returning something. Errors can and do happen for whatever reason, and its a good idea to account for them even if you already validated your data (you never know). Coding practices suggest that more than a couple of nested ifs is bad practice. A personal preference of mine is to check for failure rather than success all the way down the chain until the last lines of the function (if it got that far than everything is good to go).
A scheme like this I usually use:
public function something() {
if (!$insert_genre) {
// add flash error message
// redirect to controller
}
if (!$insert_tags) {
// add flash error message
// redirect to controller
}
if (!$insert_content_warning) {
// add flash error message
// redirect to controller
}
// yay, something went right!
}
In this kindof circumstance it is very procedural. The most important conditions should be first, and if C depends on A, then A should be the first condition.
Unrelated:
It is hard to follow some of your text here, but it also seems like you should look into how you are doing the genres. If the entered genre already exists in the database do you really need to add it? Shouldn't you just use a relationship there storing the id in the main table and joining when displaying?

Data not saved in database cakephp

I have an event table with this fields:
I use this code to insert data in this table :
$oneEvent = array(
'trainer_id' => $event['trainer_id'],
'formation_id' => $event['formation_id'],
'title' => $event['title'],
'start' => $event['start'][$i],
'end' => $event['end'][$i],
);
$success = $this->Event->save($oneEvent);
$events_id= $this->Event->inserted_ids;
when I run this code I get true and ID of insert element (showed using debug)
but in database i can't see this field never !!!!.
and when I insert data in phpmyadmin when this request INSERT INTO events(title,start, end, trainer_id, formation_id) VALUES ('Départ B','2016-11-18 10:00:00','2016-11-18 11:00:00','13','1') it worked
I didn't know what happen here !!??
I solved the problem by using $dataSource->commit(); after calling save() function

update json file dynamically whenever mysql is updated

i am going to create a live score board using php and mysql. But i want to create a json file which update automatically whenever i update my table on database. i mean new scores added in tables should be added in my json file. Really confused. sorry for not having any program. hope for some solutions. Thank you. i have some code which i have used to insert in database.
$data = array(
'name' => $name,
'score' => $score,
'comment' => $comment
);
$result=$this->db->insert('score', $data);
Do not quite understand what you want, I developed this code, see if it is what you need.
https://gist.github.com/juniorb2ss/7431040
Example:
public function __construct()
{
$this->load->helper('json');
}
public function index()
{
$data = array(
'name' => $name,
'score' => $score,
'comment' => $comment
);
save($data);
$result = $this->db->insert('score', $data);
}
File is created in folder application/cache/score.cache. Content is all scores the application.
You can enter a new score or update, the file will be updated.
Example cache content:
{"teste":{"name":"teste","score":"32","comment":"score comment"}}
The most direct solution would be to dump the whole of your score table as a JSON object on each insert. The problem with this approach is that if you have a large amount of data, on each insert you'll be selecting a lot of data.
function SelectScores()
{
$query = $this->db->query('SELECT * FROM score');
return $query->result();
}
You can then json_encode this result and save as file.

Symfony sfWidgetFormDoctrineChoice with multiple option on

I have created a form in which i embed another form. My question is about this embedded form - I'm using a sfWidgetFormDoctrineChoice widget with option multiple set to true. The code for this embedded form's configure method:
public function configure()
{
unset($this['prerequisite_id']);
$this->setWidget('prerequisite_id', new sfWidgetFormDoctrineChoice(array(
'model' => 'Stage',
'query' => Doctrine_Query::create()->select('s.id, s.name')->from('Stage s')->where('s.workflow_id = ?', $this->getOption('workflow_id') ),
'multiple' => true
)));
$this->setValidator('prerequisite_id', new sfValidatorDoctrineChoice(array(
'model' => 'Stage',
'multiple' => true,
'query' => Doctrine_Query::create()->select('s.id, s.name')->from('Stage s')->where('s.workflow_id = ?', $this->getOption('workflow_id') ),
'column' => 'id'
)));
}
I unset the prerequisite_id field because it is included in the base form, but I want it to be a multiple select.
Now, when I added the validator, everything seems to work (it passes the validation), but it seems like it has problems saving the records if there is more than one selection sent.
I get this PHP warning after submitting the form:
Warning: strlen() expects parameter 1 to be string, array given in
D:\Development\www\flow_dms\lib\vendor\symfony\lib\plugins\sfDoctrinePlugin\lib\database\sfDoctrineConnectionProfiler.class.php
on line 198
and more - I know, why - in symfony's debug mode I can see the following in the stack trace:
at Doctrine_Connection->exec('INSERT INTO stage_has_prerequisites
(prerequisite_id, stage_id) VALUES (?, ?)', array(array('12', '79'),
'103'))
So, what Symfony does is send to Doctrine an array of choices - and as I see in the debug sql query, Doctrine cannot render the query correctly.
Any ideas how to fix that? I would need to have two queries generated for two choices:
INSERT INTO stage_has_prerequisites (prerequisite_id, stage_id) VALUES (12, 103);
INSERT INTO stage_has_prerequisites (prerequisite_id, stage_id) VALUES (79, 103);
stage_id is always the same (I mean, it's set outside this form by the form in which it is embedded).
I have spend 4 hours on the problem already, so maybe someone is able to provide some help.
Well, I seem to have found a solution (albeit not the best one, I guess). Hopefully it'll be helpful to somebody.
Finally, after much thinking, I have concluded that if the problem comes from the Doctrine_Record not being able to save the record if it encounters an array instead of a single value, then the easiest solution would be to overwrite the save() method of the Doctrine_Record. And that's what I did:
class StageHasPrerequisites extends BaseStageHasPrerequisites
{
public function save(Doctrine_Connection $conn = null)
{
if( is_array( $this->getPrerequisiteId() ) )
{
foreach( $this->getPrerequisiteId() as $prerequisite_id )
{
$obj = new StageHasPrerequisites();
$obj->setPrerequisiteId( $prerequisite_id );
$obj->setStageId( $this->getStageId() );
$obj->save();
}
}
else
{
parent::save($conn);
}
}
(...)
}
So now if it encounters an array instead of a single value, it just creates a temporary object and saves it for each of this array's values.
Not an elegant solution, definitely, but it works (keep in mind that it is written for the specific structure of the data and it's just the effect of my methodology, namely See What's Wrong In The Debug Mode And Then Try To Correct It Any Way Possible).

Categories