LEFT JOIN in ZF2 using TableGateway - mysql

I have a table:
*CREATE TABLE IF NOT EXISTS `blogs_settings` (
`blog_id` int(11) NOT NULL AUTO_INCREMENT,
`owner_id` int(11) NOT NULL,
`title` varchar(255) NOT NULL,
`meta_description` text NOT NULL,
`meta_keywords` text NOT NULL,
`theme` varchar(25) NOT NULL DEFAULT 'default',
`is_active` tinyint(1) NOT NULL DEFAULT '1',
`date_created` int(11) NOT NULL,
PRIMARY KEY (`blog_id`),
KEY `owner_id` (`owner_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;*
And the second table:
*CREATE TABLE IF NOT EXISTS `users` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`password` varchar(128) NOT NULL,
`sex` tinyint(1) NOT NULL,
`birthday` date NOT NULL,
`avatar_id` int(11) DEFAULT NULL,
`user_level` tinyint(1) NOT NULL DEFAULT '1',
`date_registered` int(11) NOT NULL,
`is_active` tinyint(1) NOT NULL DEFAULT '0',
`is_banned` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`user_id`),
KEY `is_active` (`is_active`),
KEY `user_level` (`user_level`),
KEY `is_banned` (`is_banned`),
KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;*
How may I select all the fields from blogs_settings table and join only the 'username' field from the users table using TableGateway in ZF2, on blogs_settings.owner_id = users.user_id. Thanks in advance. Your help is much appreciated.
EDIT:
namespace Object\Model;
use Zend\Db\TableGateway\TableGateway;
use Zend\Db\Sql\Select;
class BlogsSettingsTable {
protected $tableGateway;
protected $select;
public function __construct(TableGateway $tableGateway) {
$this->tableGateway = $tableGateway;
$this->select = new Select();
}
public function getBlogs($field = '', $value = '') {
$resultSet = $this->tableGateway->select(function(Select $select) {
$select->join('users', 'blogs_settings.owner_id = users.user_id', array('username'));
});
return $resultSet;
}
public function getBlog($blogID) {
$id = (int) $blogID;
$rowset = $this->tableGateway->select(array('blog_id' => $id));
$row = $rowset->current();
if (!$row) {
throw new Exception('Could not find row with ID = ' . $id);
}
return $row;
}
public function addBlog(BlogsSettings $blog) {
$data = array(
'owner_id' => $blog->owner_id,
'title' => $blog->title,
'meta_description' => $blog->meta_description,
'meta_keywords' => $blog->meta_keywords,
'theme' => $blog->theme,
'is_active' => $blog->is_active,
'date_created' => $blog->date_created,
);
$this->tableGateway->insert($data);
}
public function deleteBlog($blogID) {
return $this->tableGateway->delete(array('blog_id' => $blogID));
}
}
With this, it executes the following query:
SELECT blogs_settings.*, users.username AS username FROM blogs_settings INNER JOIN users ON blogs_settings.owner_id = users.user_id
but the resultSet does not contain the username field from the joined 'users' table. However, when I run the query in phpmyadmin, everything is okay and I have the 'username' field from the 'users' table joined. What's the problem?
EDIT 2
ok, I now tried the following:
public function getBlogs() {
$select = $this->tableGateway->getSql()->select();
$select->columns(array('blog_id', 'interest_id', 'owner_id', 'title', 'date_created'));
$select->join('users', 'users.user_id = blogs_settings.owner_id', array('username'), 'left');
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet;
}
the executed query is:
SELECT `blogs_settings`.`blog_id` AS `blog_id`, `blogs_settings`.`interest_id` AS `interest_id`, `blogs_settings`.`owner_id` AS `owner_id`, `blogs_settings`.`title` AS `title`, `blogs_settings`.`date_created` AS `date_created`, `users`.`username` AS `username` FROM `blogs_settings` LEFT JOIN `users` ON `users`.`user_id` = `blogs_settings`.`owner_id`
When I run it into phpmyadmin, it joins the username field from the users table. When in zf2, it doesn't.
Here's the dump of the whole object:
Zend\Db\ResultSet\ResultSet Object
(
[allowedReturnTypes:protected] => Array
(
[0] => arrayobject
[1] => array
)
[arrayObjectPrototype:protected] => Object\Model\BlogsSettings Object
(
[blog_id] =>
[interest_id] =>
[owner_id] =>
[title] =>
[meta_description] =>
[meta_keywords] =>
[theme] =>
[is_active] =>
[date_created] =>
)
[returnType:protected] => arrayobject
[buffer:protected] =>
[count:protected] => 1
[dataSource:protected] => Zend\Db\Adapter\Driver\Pdo\Result Object
(
[statementMode:protected] => forward
[resource:protected] => PDOStatement Object
(
[queryString] => SELECT `blogs_settings`.`blog_id` AS `blog_id`, `blogs_settings`.`interest_id` AS `interest_id`, `blogs_settings`.`owner_id` AS `owner_id`, `blogs_settings`.`title` AS `title`, `blogs_settings`.`date_created` AS `date_created`, `users`.`username` AS `username` FROM `blogs_settings` LEFT JOIN `users` ON `users`.`user_id` = `blogs_settings`.`owner_id`
)
[options:protected] =>
[currentComplete:protected] =>
[currentData:protected] =>
[position:protected] => -1
[generatedValue:protected] => 0
[rowCount:protected] => 1
)
[fieldCount:protected] => 6
[position:protected] =>
)
Up... any ideas?

Adding to #samsonasik's answer and addressing the issues in its comments. You won't be able to get the joined values out of what is returned from that statement. That statement returns the model object which won't have the joined rows. You'll need to execute it as SQL at a level which will prepare it as raw SQL and return you each resulting row as an array rather than an object:
$sqlSelect = $this->tableGateway->getSql()->select();
$sqlSelect->columns(array('column_name_yourtable'));
$sqlSelect->join('othertable', 'othertable.id = yourtable.id', array('column_name_othertable'), 'left');
$statement = $this->tableGateway->getSql()->prepareStatementForSqlObject($sqlSelect);
$resultSet = $statement->execute();
return $resultSet;
//then in your controller or view:
foreach($resultSet as $row){
print_r($row['column_name_yourtable']);
print_r($row['column_name_othertable']);
}

if you're using TableGateway, you can select join like this
$sqlSelect = $this->tableGateway->getSql()->select();
$sqlSelect->columns(array('column_name'));
$sqlSelect->join('othertable', 'othertable.id = yourtable.id', array(), 'left');
$resultSet = $this->tableGateway->selectWith($sqlSelect);
return $resultSet;

You have to include username field in the BlogsSetting Model that is used as model from BlogsSettingTable (The TableGateway)
class BlogsSetting {
public $blog_id;
public $interest_id;
public $owner_id;
public $title;
public $meta_description;
public $meta_keywords;
public $theme;
public $is_active;
public $date_created;
public $username;
public function exchangeArray($data)
{
// Create exchangeArray
}
}
Hope this helps

This is the exact need for both Join and Where clauses with tableGateway.
public function getEmployeefunctionDetails($empFunctionId) {
$empFunctionId = ( int ) $empFunctionId;
//echo '<pre>'; print_r($this->tableGateway->getTable()); exit;
$where = new Where();
$where->equalTo('FUNCTION_ID', $empFunctionId);
$sqlSelect = $this->tableGateway->getSql()->select()->where($where);
$sqlSelect->columns(array('FUNCTION_ID'));
$sqlSelect->join('DEPARTMENTS', 'DEPARTMENTS.DEPARTMENT_ID = EMPLOYEE_FUNCTIONS.DEPARTMENT_ID', array('DEPARTMENT_ID','DEPARTMENT_NAME'), 'inner');
$sqlSelect->join('ROLES', 'ROLES.ROLE_ID = EMPLOYEE_FUNCTIONS.ROLE_ID', array('ROLE_ID','ROLE_NAME'), 'inner');
//echo $sqlSelect->getSqlString(); exit;
$resultSet = $this->tableGateway->selectWith($sqlSelect);
if (! $resultSet) {
throw new \Exception ( "Could not find row $empFunctionId" );
}
return $resultSet->toArray();
}

In your class inherited from AbstractTableGateway u can use Select with Closure like this:
use Zend\Db\Sql\Select;
...
public function getAllBlockSettings()
{
$resultSet = $this->select(function(Select $select) {
$select->join('users', 'blogs_settings.owner_id = users.user_id', array('username'));
});
return $resultSet;
}

Give it a try:
namespace Object\Model;
use Zend\Db\TableGateway\AbstractTableGateway;
use Zend\Db\Sql\Select;
class BlogsSettingsTbl extends AbstractTableGateway {
public function __construct($adapter) {
$this->table = 'blogs_settings';
$this->adapter = $adapter;
$this->initialize();
}
public function fetchAll() {
$where = array(); // If have any criteria
$result = $this->select(function (Select $select) use ($where) {
$select->join('users', 'blogs_settings.owner_id = users.user_id', array('username'));
//echo $select->getSqlString(); // see the sql query
});
return $result;
}
}
Add to 'getServiceConfig()' in Module.php:
'Object\Model\BlogsSettingsTbl' => function($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$table = new BlogsSettingsTbl($dbAdapter); // <-- also add this to 'USE' at top
return $table;
},

since the OP hasn't accepted any answer, I'll try to give the solution.
I face the same solution as the OP states and the only way to fix it is by adding this line to the model class (in this case this might be 'Blogsetttings.php').
$this->username= (!empty($data['username'])) ? $data['username'] : null;
you should add above line to the exchangeArray() method.
Hope it helps

Related

Laravel - How do update a table immediately records are saved in it

In my Laravel-5.8, I have this table.
CREATE TABLE `appraisal_goal_types` (
`id` int(11) NOT NULL,
`name` varchar(200) NOT NULL,
`parent_id` int(11) DEFAULT NULL,
`max_score` int(11) DEFAULT 0,
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Then I created this controller to store record in another table.
public function store(StoreAppraisalGoalRequest $request)
{
$appraisalStartDate = Carbon::parse($request->appraisal_start_date);
$appraisalEndDate = Carbon::parse($request->appraisal_end_date);
$userCompany = Auth::user()->company_id;
$employeeId = Auth::user()->employee_id;
$identities = DB::table('appraisal_identity')->select('id','appraisal_name')->where('company_id', $userCompany)->where('is_current', 1)->first();
try {
$goal = new AppraisalGoal();
$goal->goal_type_id = $request->goal_type_id;
$goal->appraisal_identity_id = $request->appraisal_identity_id;
$goal->employee_id = $employeeId; //$request->employees_id
$goal->weighted_score = $request->weighted_score;
$goal->goal_title = $request->goal_title;
$goal->goal_description = $request->goal_description;
$goal->company_id = Auth::user()->company_id;
$goal->created_by = Auth::user()->id;
$goal->created_at = date("Y-m-d H:i:s");
$goal->is_active = 1;
if ($request->appraisal_doc != "") {
$appraisal_doc = $request->file('appraisal_doc');
$new_name = rand() . '.' . $appraisal_doc->getClientOriginalExtension();
$appraisal_doc->move(public_path('storage/documents/appraisal_goal'), $new_name);
$goal->appraisal_doc = $new_name;
}
$goal->save();
$parentids = DB::table('appraisal_goal_types')->select('parent_id')->whereNotNull('parent_id')->where('company_id', $userCompany)->where('id', $goal->goal_type_id)->first();
$parentid = $parentids->id;
$goal->update(['parent_id' => $parentid]);
}
As soon as the record is saved, I want to quickly query appraisal_goal_types
$parentids = DB::table('appraisal_goal_types')->select('parent_id')->whereNotNull('parent_id')->where('id', $goal->goal_type_id)->first();
$parentid = $parentids->id;
$goal->update(['parent_id' => $parentid]);
and update the record.
I need only one row there where the answer is true. I used the code above, but nothing is happening.
How do I resolve this?
Thank you
Try like this,
$parentids = DB::table('appraisal_goal_types')->select('parent_id')->whereNotNull('parent_id')->where('company_id', $userCompany)->where('id', $goal->goal_type_id)->first();
$parentid = $parentids->id;
$goal->parent_id = $parentid;
$goal->save();
There is an another solution like this,
$parentids = DB::table('appraisal_goal_types')->select('parent_id')->whereNotNull('parent_id')->where('company_id', $userCompany)->where('id', $goal->goal_type_id)->first();
$parentid = $parentids->id;
AppraisalGoal::where('id', $goal->id)->update(['parent_id' => $parentid]);
Both will works. And let me know if you solved the issue

Storing 2 same id of post table with different language into database

I'm building a multi language website. In this case just 2 languages, it's Indonesian and English using Laravel.
I have posts table, it will store id of each post and post_translations table is to store local, title, and description of post.
I got the problem when storing data into database. I don't have any idea how to store post without inc the id except I've added 2 same post with Indonesian and English.
This is the result (wrong)
posts table
id
1
2
post_translations table
id post_id locale title
1 1 en fisrt post
2 2 id post yang pertama
Expexted result
posts table
id
1
post_translations table
id post_id locale title
1 1 en fisrt post
2 1 id post yang pertama
PostController
public function store(Request $request) {
$this->validate($request, [
'title' => 'required',
'slug' => 'required',
'content' => 'required'
]);
$post = new Post;
$post->title = $request->title;
$post->slug = $request->slug;
$post->content = $request->content;
$post->save();
return redirect()->route('post.index');
}
Ok, so here we go (please note that this is not the only way):
install spatie/laravel-translatable with
composer require spatie/laravel-translatable
**Note: for native spatie/laravel-translatable go to version 2 **
create a table with this structure:
CREATE TABLE articles (
id int(10) UNSIGNED NOT NULL,
title text COLLATE utf8_unicode_ci,
slug text COLLATE utf8_unicode_ci,
content text COLLATE utf8_unicode_ci,
created_at timestamp NULL DEFAULT NULL,
updated_at timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Note: beter use a migration. I just exported a table I did earlier to test
Insert the data in the datatabase in json format like this:
INSERT INTO `pages` (`id`, `title`, `slug`, `content`, `created_at`, `updated_at`) VALUES
(1, '{"ro":"Acas\\u0103","en":"Home"}', NULL, '{"ro":"<p><strong>Test title<\\/strong><\\/p>\\r\\n\\r\\n<p>Test content romanian<\\/p>\\r\\n","en":"<p><strong>test title english<\\/strong><\\/p>\\r\\n\\r\\n<p>test content english.<\\/p>\\r\\n"}', '2017-04-03 11:45:56', '2017-04-03 12:15:16');
Now create the blade to edit, update, create show etc. To get the language do something like this in the blade:
{{ $data->title }}
{!! nl2br($data->content) !!}
And in the controller:
add something like this:
/**
* Generate the field by language
*
* #param Model $entry the item selected from the database
*
* #return array
*/
public function getTranslatableFields($fields)
{
$inputs = [];
$languages = $this->getLanguages();
foreach ($languages as $language) {
foreach ($fields as $field) {
$inputs[] = [
'name' => "{$field['name']}[{$language->abbr}]",
'label' => $field['label'] . " ($language->abbr)",
'lang' => $language->abbr,
'type' => array_key_exists('type', $field) ? $field['type'] : 'text'
];
}
}
return $inputs;
}
I added this function in a LangTrait. Since I also use backpack for laravel I did some more things.
For edit I added this method in the trait:
/**
* Show the form for editing the specified resource.
*
* #param int $id the item's identifier
*
* #return Response
*/
public function edit($id)
{
$data['entry'] = Model::find($id);
$data['title'] = trans('lang_file.edit').' '.$this->entity_name; // name of the page
$data['fields'] = $this->getMultiLangFields($data['entry']);
$data['id'] = $id;
return view('crud::edit', $data);
}
/**
* Generate the field by language
*
* #param Model $entry the item selected from the database
*
* #return array
*/
protected function getMultiLangFields($entry)
{
$fields['id'] = ['name' => 'id', 'type' => 'hidden', 'value' => $entry->id];
foreach ($this->crud->update_fields as $key => $field) {
$value = null;
if (array_key_exists('lang', $field)) {
$name = preg_replace('/(\[\w{2}\])$/i', '', $field['name']);
$value = $entry->getTranslation($name, $field['lang']);
}
$fields[$key] = array_merge($field, ['value' => $value]);
}
return $fields;
}
/**
* Get the application active languages
*
* #return \Backpack\LangFileManager\app\Models\Language
*/
protected function getLanguages()
{
return Language::whereActive(1)->orderBy('default', 'desc')->get();
}
Finally in my main controller I did:
use LangTrait; (contains everything above)
In construct I added this:
$this->getTranslatableFields($fields)
where $fields it's the list of fields I need
All methods should be adapted to you html format. As I said I use backpack for laravel and fields are formatted accordingly
And finally for the getLanguage file to work I created a new table and a model in the DB:
Model:
class Language extends Model
{
protected $table = 'languages';
protected $fillable = ['name', 'flag', 'abbr', 'native', 'active', 'default'];
public $timestamps = false;
public static function getActiveLanguagesArray()
{
$active_languages = self::where('active', 1)->get()->toArray();
$localizable_languages_array = [];
if (count($active_languages)) {
foreach ($active_languages as $key => $lang) {
$localizable_languages_array[$lang['abbr']] = $lang;
}
return $localizable_languages_array;
}
return config('laravellocalization.supportedLocales');
}
public static function findByAbbr($abbr = false)
{
return self::where('abbr', $abbr)->first();
}
}
Table:
CREATE TABLE `languages` (
`id` int(10) UNSIGNED NOT NULL,
`name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`app_name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`flag` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`abbr` varchar(3) COLLATE utf8_unicode_ci NOT NULL,
`script` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
`native` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
`active` tinyint(3) UNSIGNED NOT NULL DEFAULT '1',
`default` tinyint(3) UNSIGNED NOT NULL DEFAULT '0',
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`deleted_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Data in the table:
INSERT INTO `languages` (`id`, `name`, `app_name`, `flag`, `abbr`, `script`, `native`, `active`, `default`, `created_at`, `updated_at`, `deleted_at`) VALUES
(1, 'English', 'english', '', 'en', 'Latn', 'English', 1, 0, NULL, NULL, NULL),
(2, 'Romanian', 'romanian', '', 'ro', 'Latn', 'română', 1, 1, NULL, NULL, NULL);
Since I did this through a package I kind of messed around a little bit with the code.
Now, for the spatie/laravel-translatable package version:
set up the service provider in config/app.php add this in the providers array:
Spatie\Translatable\TranslatableServiceProvider::class,
In the model Articles add use HasTranslations; like this:
use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;
class NewsItem extends Model
{
use HasTranslations;
public $translatable = ['name']; // list the columns you want to be translatable (will have json format)
}
save a new entry and use it:
$article = new Article;
$article->setTranslation('name', 'en', 'Updated name in English')
->setTranslation('name', 'nl', 'Naam in het Nederlands');
$article->save();
$article->name; // Returns 'Name in English' given that the current app locale is 'en'
$article->getTranslation('name', 'nl'); // returns 'Naam in het Nederlands'
app()->setLocale('nl');
$article->name; // Returns 'Naam in het Nederlands'
examples from: https://github.com/spatie/laravel-translatable
Database table format is as stated above in the first version
If it does not work out let me know and I'll look at your code.
I think you should change your tables strucuture:
posts : id, slug.
post_translations : id, post_id, locale, title, content
Also add relation to your Post model:
public function translations()
{
return $this->hasMany(PostTranslation::class, 'post_id');
}
And update your controller:
$post = new Post;
$post->slug = $request->slug;
$post->save();
$post->translations()->create([
'locale' => 'en', //or grab it from $request
'title' => $request->title,
'content' => $request->content
])
It will create your post and add translation to it

Yii2 using ActiveQuery that uses sub-query on same Model

I have a Comments table that have parent_id foreign key that points to itself to enable threaded comment.
Comments
id INT UNSIGNED NOT NULL
parent_id INT UNSIGNED NULL
comment TEXT NOT NULL
created_time DATETIME NOT NULL
The original ActiveQuery is like this
class CommentActiveQuery extends \yii\db\ActiveQuery {
public function andWhereIsNotRemoved() {
return $this->andWhere(['isRemoved' => Comment::STATUS_IS_NOT_REMOVED]);
}
public function andWhereParentIdIs($parentId) {
return $this->andWhere(['parentId' => $parentId]);
}
public function orderByNewestCreatedTime() {
return $this->orderBy(['createdTime' => SORT_DESC]);
}
}
Now I want to sort the comments by the newest active reply.
The query is basically like this
SELECT `*`, `last_reply_time`
FROM `Comments`
WHERE `parent_id` IS NULL
ORDER BY `last_reply_time` DESC;
I'm thinking the last_reply_time is a subquery
SELECT MAX(created_time)
FROM `Comments`
WHERE `parent_id` = :something
How to build this using the CommentActiveQuery above. The farthest I can get is like this
public function orderByNewestActiveChildCreatedTime() {
return $this->addSelect([
'last_reply_time' => $subQuery
])->orderBy(['last_reply_time' => SORT_DESC]);
}
With what should I replace the $subQuery variable above? Or is there a better way?
$subQuery = new \yii\db\Query();
$subQuery->select(["max(subQ.created_time)"]);
$subQuery-> from('comments subQ');
$subQuery->where([
'parent_id' => $parentId
]);
$query = new \yii\db\Query();
$query->select([
'C.*',
$subQuery
]);
$query->from('Comments C');
$query->andWhere(
'parent_id is Null'
);
$command = $query->createCommand();
/*
Printing the command will result following sql with $parentId = 1
SELECT
`C`.*, (
SELECT
max(subQ.created_time)
FROM
`comments` `subQ`
WHERE
`parent_id` =: qp0
) AS `1`
FROM
`Comments` `C`
WHERE
parent_id IS NULL
*/
print_r($command->sql);
I am not sure about ORDER BY last_reply_time DESC; Assuming last_reply_time is db table attribute and is different from the subquery. You can simply add orderBy in the query by doing $query->orderBy('last_reply_time DESC')
I hope this would be helpful to you.Cheers :)

CodeIgniter Select Query with password function

what is the process for using mysql password function in codeIgniter.
my controller
$where = array(
"studentid" => $this->input->post('username'),
"password" => "password('".$this->input->post('password')."')",
"status" =>1
);
$user = $this->void->getData("users",$where);
my model function
public function getData($table,$where,$order = 'id')
{
$this->db->order_by($order);
$this->db->where($where);
$query=$this->db->get($table);
return $query->result();
}
this is not working. this is generating following query as you can see the problem
SELECT * FROM (`users`) WHERE `studentid` = '054418' AND `password` = 'password(\'054418\')' AND `status` = 1 ORDER BY `id`
please help me with solution. thanks in advance for helping
Try this if it helps:
$this->db->where($where, null, false);
Try this:
$where = " `studentid` = '".$this->input->post('username')."' AND
`password` = password('".$this->input->post('password')."') AND
`status` = 1";

how to get last insert id after insert query in codeigniter active record

I have an insert query (active record style) used to insert the form fields into a MySQL table. I want to get the last auto-incremented id for the insert operation as the return value of my query but I have some problems with it.
Inside the controller:
function add_post(){
$post_data = array(
'id' => '',
'user_id' => '11330',
'content' => $this->input->post('poster_textarea'),
'date_time' => date("Y-m-d H:i:s"),
'status' => '1'
);
return $this->blog_model->add_post($post_data);
}
And inside model:
function add_post($post_data){
$this->db->trans_start();
$this->db->insert('posts',$post_data);
$this->db->trans_complete();
return $this->db->insert_id();
}
I get nothing as the return of the add_post in model
Try this
function add_post($post_data){
$this->db->insert('posts', $post_data);
$insert_id = $this->db->insert_id();
return $insert_id;
}
In case of multiple inserts you could use
$this->db->trans_start();
$this->db->trans_complete();
A transaction isn't needed here, this should suffice:
function add_post($post_data) {
$this->db->insert('posts',$post_data);
return $this->db->insert_id();
}
$id = $this->db->insert_id();
From the documentation:
$this->db->insert_id()
The insert ID number when performing database inserts.
Therefore, you could use something like this:
$lastid = $this->db->insert_id();
Using the mysqli PHP driver, you can't get the insert_id after you commit.
The real solution is this:
function add_post($post_data){
$this->db->trans_begin();
$this->db->insert('posts',$post_data);
$item_id = $this->db->insert_id();
if( $this->db->trans_status() === FALSE )
{
$this->db->trans_rollback();
return( 0 );
}
else
{
$this->db->trans_commit();
return( $item_id );
}
}
Source for code structure: https://codeigniter.com/user_guide/database/transactions.html#running-transactions-manually
It is worth saying that the other answers relate to Codeigniter version 3. The answer in Version 4 (found https://codeigniter.com/user_guide/database/helpers.html) is to use $this->db->insertID()
because you have initiated the Transaction over the data insertion so,
The first check the transaction completed or not. once you start the transaction, it should be committed or rollback according to the status of the transaction;
function add_post($post_data){
$this->db->trans_begin()
$this->db->insert('posts',$post_data);
$this->db->trans_complete();
if ($this->db->trans_status() === FALSE){
$this->db->trans_rollback();
return 0;
}else{
$this->db->trans_commit();
return $this->db->insert_id();
}
}``
in the above, we have committed the data on the successful transaction even you get the timestamp
Just to complete this topic:
If you set up your table with primary key and auto increment you can omit the process of manually incrementing the id.
Check out this example
if (!$CI->db->table_exists(db_prefix() . 'my_table_name')) {
$CI->db->query('CREATE TABLE `' . db_prefix() . "my_table_name` (
`serviceid` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`name` varchar(64) NOT NULL,
`hash` varchar(32) NOT NULL,
`url` varchar(120) NOT NULL,
`datecreated` datetime NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT '1'
) ENGINE=InnoDB DEFAULT CHARSET=" . $CI->db->char_set . ';');
Now you can insert rows
$this->db->insert(db_prefix(). 'my_table_name', [
'name' => $data['name'],
'hash' => app_generate_hash(),
'url' => $data['url'],
'datecreated' => date('Y-m-d H:i:s'),
'active' => $data['active']
]);
**Inside Model**
function add_info($data){
$this->db->insert('tbl_user_info',$data);
$last_id = $this->db->insert_id();
return $last_id;
}
**Inside Controller**
public function save_user_record() {
$insertId = $this->welcome_model->save_user_info($data);
echo $insertId->id;
}
You must use $lastId = $this->db->insert_id();