Bir önceki OpenCart 4 İçin Nasıl Eklenti Geliştirilir? başlıklı yazımızda başladığımız eklenti geliştirme sürecimize kendi veritabanı tablomuzu nasıl ekleyeceğimizi görerek devam edeceğiz. Eğer okumadıysanız bir önceki yazıdan başlamanız önem arz etmektedir.
Bir önceki yazıda geliştirdiğimiz eklenti setting/module
modelini kullanarak
tablosuna modülümüzü ilgili form verileri ile birlikte kaydediyordu. Ardından sayfa tasarımlarımızda modülü istediğimiz gibi kullanabiliyorduk." . DB_PREFIX . "module
Eklentimiz yapısı gereği sadece HTML içeriğini kaydedip arayüzde göstermeye çalışıyordu. Şimdi bu eklentimizi kendi veritabanı tablosundan veri çekip basitçe HTML tablo içerisinde listeleyen bir hale getirelim.
İlk adım olarak extension/sustartx/admin/model/html_content.php
modelimize aşağıdaki gibi değiştirelim.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
<?php namespace Opencart\Admin\Model\Extension\SuStartX\Module; class HtmlContent extends \Opencart\System\Engine\Model { public function example($data) { $this->db->query("select * from ..."); } public function isDatabaseExists(): bool{ $table = DB_PREFIX . $this->db->escape('sustartx_html_contents'); $query = $this->db->query("SHOW TABLES LIKE '{$table}'"); return (bool)$query->num_rows; } public function createTables(): void{ $this->db->query( "CREATE TABLE IF NOT EXISTS ". DB_PREFIX . "sustartx_html_contents ( `id` int(16) NOT NULL AUTO_INCREMENT, `module_id` int(16) NOT NULL, `title` varchar(256) NOT NULL, `description` text NOT NULL, `status` tinyint(1) NOT NULL, `created_at` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1" ); } public function addContent($data) { $this->db->query("INSERT INTO `" . DB_PREFIX . "sustartx_html_contents` SET module_id = '" . $this->db->escape($data['module_id']) . "', title = '" . $this->db->escape($data['title']) . "', description = '" . $this->db->escape($data['description']) . "', status = '" . (int)$data['status'] . "', created_at = NOW() "); return $this->db->getLastId(); } public function deleteContent($content_id) { $this->db->query("DELETE FROM `" . DB_PREFIX . "sustartx_html_contents` WHERE id = '" . (int)$content_id . "'"); } public function getContents($module_id) { $sql = "SELECT * FROM `" . DB_PREFIX . "sustartx_html_contents` where module_id = " . $module_id; $query = $this->db->query($sql); return $query->rows; } } |
Modelimize ihtiyacımız olan birkaç method eklenmiş oldu.
Şimdi HTMLContent
controller dosyamızda namespace
satırının hemen altına aşağıdaki satırı ekleyelim.
1 |
require_once DIR_EXTENSION . '/sustartx/admin/model/module/html_content.php'; |
Böylelikle model model dosyamızı da kullanabilir olacağız. Ardından aynı dosyaya birkaç method eklememiz gerekiyor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
public function add_content(){ $this->checkDatabase(); $this->load->language('extension/sustartx/module/html_content'); $json = []; if (!$this->user->hasPermission('modify', 'extension/sustartx/module/html_content')) { $json['error']['warning'] = $this->language->get('error_permission'); } if (!$this->request->post['content_title']) { $json['error']['content_title'] = $this->language->get('error_content_title'); } if (!$this->request->post['content_description']) { $json['error']['content_description'] = $this->language->get('error_content_description'); } if (!$json) { $data = $this->request->post; $this->load->model('extension/sustartx/module/html_content'); $content = [ 'module_id' => $data['module_id'], 'title' => $data['content_title'], 'description' => $data['content_description'], 'status' => $data['content_status'], ]; $this->model_extension_sustartx_module_html_content->addContent($content); $json['success'] = $this->language->get('text_success'); } $this->response->addHeader('Content-Type: application/json'); $this->response->setOutput(json_encode($json)); } public function remove_content(){ $this->load->language('extension/sustartx/module/html_content'); $json = []; if (!$this->user->hasPermission('modify', 'extension/sustartx/module/html_content')) { $json['error']['warning'] = $this->language->get('error_permission'); } if (array_key_exists('content_id', $this->request->post) && (int)$this->request->post['content_id'] > -1){ $content_id = $this->request->post['content_id']; $module_id = $this->request->post['module_id']; $this->load->model('setting/module'); $module_info = $this->model_setting_module->getModule($module_id); if ($module_info){ $this->load->model('extension/sustartx/module/html_content'); $this->model_extension_sustartx_module_html_content->deleteContent($content_id); $json['success'] = $this->language->get('text_success_delete'); }else{ $json['error']['name'] = $this->language->get('error_name'); } }else{ $json['error']['name'] = $this->language->get('error_name'); } $this->response->addHeader('Content-Type: application/json'); $this->response->setOutput(json_encode($json)); } public function loadContents(){ $this->checkDatabase(); $this->load->language('extension/sustartx/module/html_content'); $module_id = (int)$this->request->get['module_id']; $data = [ 'contents' => [] ]; if ($module_id > 0) { $this->load->model('extension/sustartx/module/html_content'); $data['contents'] = $this->model_extension_sustartx_module_html_content->getContents($module_id); } $this->response->setOutput($this->load->view('extension/sustartx/module/html_content_list', $data)); } private function checkDatabase(): void{ $this->load->model('extension/sustartx/module/html_content'); if (!$check = $this->model_extension_sustartx_module_html_content->isDatabaseExists()){ $this->model_extension_sustartx_module_html_content->createTables(); } } |
Artık veritabanında işlem yapabileceğimiz örnek kodlar elimizde. Veritabanına ekleme, silme ve listeme işlemleri için örnek kodlarımız var. Güncelleme işlemini siz ihtiyacınıza uygun şekilde geliştirebilirsiniz. Bizim geliştirdiğimiz örnekte güncellemeye ihtiyacımız yok.
Şimdi dil dosyasında geçelim. Dil dosyasında birkaç noktaya satır eklediğim için tek tek satır numarası vermek yerine tüm dosya içeriğini paylaşıyorum.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?php // Heading $_['heading_title'] = 'SuStartX - HTML Content <a style="display: block; float: right; clear: both;" href="/extension/sustartx/admin/view/image/bird.svg" target="_blank"><img style="right: 0" width="25" height="25" src="/extension/sustartx/admin/view/image/bird.svg" class="text-end" /></a>'; $_['text_contents_add'] = 'Add a New Content'; $_['text_contents_list'] = 'Content List'; // Text $_['text_extension'] = 'Extensions'; $_['text_success'] = 'Success: You have modified HTML Content module!'; $_['text_success_delete'] = 'Success: The record successfully deleted'; $_['text_edit'] = 'Edit HTML Content Module'; // Column $_['column_content_title'] = 'Title'; $_['column_content_description'] = 'Description'; $_['column_content_status'] = 'Status'; $_['column_action'] = 'Action'; // Entry $_['entry_name'] = 'Module Name'; $_['entry_content'] = 'Content'; $_['entry_status'] = 'Status'; $_['entry_content_title'] = 'Title'; $_['entry_content_description'] = 'Description'; $_['entry_content_status'] = 'Status'; $_['button_content_save'] = 'Save Content'; // Error $_['error_permission'] = 'Warning: You do not have permission to modify featured single product type 2 module!'; $_['error_name'] = 'Module Name must be between 3 and 64 characters!'; $_['error_content'] = 'Content required!'; $_['error_content_title'] = 'Content title required!'; $_['error_content_description'] = 'Content description required!'; |
Son olarak view dosyasına gelelim. html_content.twig
dosyasında aşağıdaki satırı bulun.
1 |
<input type="hidden" name="module_id" value="{{ module_id }}" id="input-module-id"/> |
Hemen üstüne aşağıdaki satırları ekleyin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<div id="form-container"> <br> <fieldset> <legend> {{ text_contents_add }} </legend> <div class="row mb-3 required"> <label for="input-content-title" class="col-sm-2 col-form-label">{{ entry_content_title }}</label> <div class="col-sm-10"> <div class="input-group"> <input type="text" disabled name="input-content-title" id="input-content-title" placeholder="{{ entry_content_title }}" class="form-control"/> </div> </div> </div> <div class="row mb-3 required"> <label for="input-content-description" class="col-sm-2 col-form-label">{{ entry_content_description }}</label> <div class="col-sm-10"> <div class="input-group"> <input type="text" disabled name="input-content-description" id="input-content-description" placeholder="{{ entry_content_description }}" class="form-control"/> </div> </div> </div> <div class="row mb-3"> <label for="input-content-status" class="col-sm-2 col-form-label">{{ entry_content_status }}</label> <div class="col-sm-10"> <div class="form-check form-switch form-switch-lg"> <input type="hidden" name="input-content-status" value="0"/> <input type="checkbox" disabled name="input-content-status" value="1" id="input-content-status" class="form-check-input" /> </div> </div> </div> <div class="row mb-3"> <div class="col"> <button disabled class="btn btn-primary" id="button-content-add" type="button">{{ button_content_save }}</button> </div> </div> </fieldset> <br/> <fieldset> <legend> {{ text_contents_list }}</legend> <div id="contents"></div> </fieldset> </div> |
Ardından sayfanın altındaki script etiketini bulun. En son içini boş bırakmıştık. Şimdi o script etiketini aşıdaki gibi değiştirin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
<script type="text/javascript"> const module_id = $('#input-module-id').val(); $(document).ready(function() { const module_id = $('#input-module-id'); let currentValue = module_id.val(); if (currentValue < 1){ const interval = setInterval(function() { if (module_id.val() !== currentValue) { currentValue = module_id.val(); $('#form-container input, #form-container button').removeAttr('disabled'); clearInterval(interval) } }, 1000); }else{ $('#form-container input, #form-container button').removeAttr('disabled'); } }); loadContents() function loadContents(){ const module_id = $('#input-module-id').val(); $('#contents').load('index.php?route=extension/teknifty/module/html_content.loadContents&user_token={{ user_token }}&module_id=' + module_id); } $('#button-content-add').on('click', function () { const module_id = $('#input-module-id').val(); const data = { 'content_title': $('#input-content-title').val(), 'content_description': $('#input-content-description').val(), 'content_status': $('#input-content-status').val(), 'module_id': module_id, } $.ajax({ url: 'index.php?route=extension/teknifty/module/html_content.add_content&user_token={{ user_token }}', type: 'post', dataType: 'json', data: data, beforeSend: function () { $('#button-content-add').button('loading'); }, complete: function () { $('#button-content-add').button('reset'); }, success: function (json) { const element = $(this).closest('fieldset') $('.alert-dismissible').remove(); $(element).find('.is-invalid').removeClass('is-invalid'); $(element).find('.invalid-feedback').removeClass('d-block'); if (typeof json['error'] == 'string') { $('#alert').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>'); } if (typeof json['error'] == 'object') { if (json['error']['warning']) { $('#alert').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error']['warning'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>'); } for (key in json['error']) { $('#input-' + key.replaceAll('_', '-')).addClass('is-invalid').find('.form-control, .form-select, .form-check-input, .form-check-label').addClass('is-invalid'); $('#error-' + key.replaceAll('_', '-')).html(json['error'][key]).addClass('d-block'); } } if (json['success']) { $('#alert').prepend('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-circle-check"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>'); loadContents() $('#input-content-title').val('') $('#input-content-description').val('') $('#input-content-status').val('0') } // Replace any form values that correspond to form names. for (key in json) { $(element).find('[name=\'' + key + '\']').val(json[key]); } }, error: function (xhr, ajaxOptions, thrownError) { console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText); } }); }); $('#contents').on('click', 'button', function () { if (confirm('Are you sure ?')){ var element = this; const module_id = $('#input-module-id').val(); const content_id = $(element).val(); const data = { module_id: module_id, content_id: content_id } $.ajax({ url: 'index.php?route=extension/teknifty/module/html_content.remove_content&user_token={{ user_token }}', type: 'post', dataType: 'json', data: data, beforeSend: function () { $(element).button('loading'); }, complete: function () { $(element).button('reset'); }, success: function (json) { $('.alert-dismissible').remove(); if (json['error']) { $('#alert').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>'); } if (json['success']) { $('#alert').prepend('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-circle-check"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>'); console.log("asdasd") loadContents() } }, error: function (xhr, ajaxOptions, thrownError) { console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText); } }); } }); </script> |
Şimdi html_content.twig
dosyasının hemen yanına html_content_list.twig
dosyası oluşturun ve aşağıdaki kodları içine ekleyin.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<div class="table-responsive"> <table class="table table-bordered table-hover"> <thead> <tr> <td class="text-start">{{ column_content_title }}</td> <td class="text-start">{{ column_content_description }}</td> <td class="text-start">{{ column_content_status }}</td> <td class="text-end">{{ column_action }}</td> </tr> </thead> <tbody> {% if contents %} {% for index, content in contents %} <tr> <td class="text-start">{{ content.title }}</td> <td class="text-start">{{ content.description }}</td> <td class="text-start">{{ content.status }}</td> <td class="text-end"> <button type="button" value="{{ content.id }}" data-bs-toggle="tooltip" title="{{ button_remove }}" class="btn btn-danger"> <i class="fa-solid fa-circle-minus"></i> </button> </td> </tr> {% endfor %} {% else %} <tr> <td class="text-center" colspan="4">{{ text_no_results }}</td> </tr> {% endif %} </tbody> </table> </div> |
Artık tüm ihtiyaçlarımızı tamamlamış olduk. Eğer bir önceki yazıyı takip ederek oluşturduğunuz eklentinizin üstünde değişiklik yaptıysanız silip yeniden yüklemeye gerek kalmadan çalışması gerekiyor.
Panelde yaptığımız bu geliştirmenin catalog tarafında da görünmesini istiyorsanız benzer yolları takip ederek verileri catalog içine de çekebilirsiniz.
İlk Yorumu Siz Yapın