Use templates created using ckeditor in codeigniter - php

I am creating the templates using CKEditor. I need to replace the keys with its value, the keys are stored with its table name and columns to fetch in a table
e.g
tbl_template_bindings
id key table column
1 StudentFirstName tbl_User fname
2 StudentLastName tbl_User lname
3 TotalAmount tbl_payment due
and the user is bound to use those keys only, a kind of template. so consider we have created below template using CKEditor
Date: {{CurrentDate}}
Dear {{StudentFirstName}} {{StudentLastName}}, Your total amount is {{TotalAmount}}
please suggest any ideas will be helpful

Well, I just made this code for you, because I love CodeIgniter. Unfortunately I didn't test this code, but I am pretty sure #dEL, you will enjoy :)
CodeIgniter Helper File: Templatebuilder_helper.php
if ( ! function_exists('build_ck_template')) {
/**
* #param $template_txt
*/
function build_ck_template($template_txt)
{
// get all {{DATA}} as DATA in assoc array
preg_match_all('/{{(.*?)}}/', $template_txt, $matches);
// trim data & make array
$config = array_map('trim', $matches[1]);
// get CI instance
$CI = &get_instance();
// assuming you have user id in session - just for demo
$uid = $CI->session->userdata('uid');
// temp array var
$result = [];
// get data from table key, table & column
$query = $CI->db->query("SELECT * FROM tbl_template_bindings");
// collect all data
foreach ($query->result_array() as $row) {
array_push($result, $row);
}
// check one by one array key
foreach ($config as $key => $value) {
// skip date because its not in table
if ($value != 'CurrentDate') {
// first check if key exist in db data, get index
$found_at_index = array_search($value, array_column($result, 'key'));
// yes we got the key
if (false !== $found_at_index) {
// get data for requested key
$CI->db->select($result[$found_at_index]['column']);
// where clause
$CI->db->where('uid', $uid);
// query
$query = $CI->db->get($result[$found_at_index]['table']);
// if uid is unique, we want to return just one row
$query_result = array_shift($query->result_array());
// get key column data
$replace_value = $query_result[$result[$found_at_index]['column']];
// replace with original value
$template_txt = str_replace('{{'.$value.'}}', $replace_value, $template_txt);
}
}
}
// return Woah!!!
$template_txt = str_replace('{{CurrentDate}}', date('Y-m-d'), $template_txt);
return $template_txt;
}
}
/* End of file Templatebuild_helper.php */
/* Location: ./application/helpers/Templatebuilder_helper.php */
Example Uses:
<?php
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Class Controller
*/
class ControllerName extends CI_Controller {
public function __construct()
{
parent::__construct();
// load own template helper
$this->load->helper('Templatebuilder');
}
public function index()
{
// content template
$content = "Date: {{CurrentDate}}, Dear {{StudentFirstName}} {{StudentLastName}}, Your total amount is {{TotalAmount}}";
// build with real values
$this->load->view('template', array('temp_data' => build_ck_template($content)));
}
}
/* End of file data.php */
/* Location: ./application/controllers/ControllerName.php */

i'm not sure, but if i understand you correctly you simply need to parse some values and replace it with others
just create a model
class Template_Model extends CI_Model
{
public function build($strTemplate, $obj)
{
$arrData = (is_object($obj)) ? get_object_vars($obj) : $obj;
foreach($arrData AS $key => $val)
{
$strTemplate = str_replace("{{".$key."}}",$val,$strTemplate);
}
return $strTemplate;
}
}
and your controller
$this->load->model("template_model");
$str = "Date: {{CurrentDate}}, Dear {{StudentFirstName}} {{StudentLastName}}, Your total amount is {{TotalAmount}}";
echo $this->template_model->build($str, ["CurrentDate" => "2017-05-02", "StudentFirstName" => "Jon", "StudentLastName" => "Doe", "TotalAmount" => 100.22]);

You can use CI parsing library to parsing your DB to HTML page.
CI parsing example

Related

Passing data between 2 models in 1 controller function laravel

I need to get the lecture id in my student table and from then only can i get the lecture's data using that id. The problem is, the $lectureID is null when i try to apply it on the lecture model, but when i check on the console, it does get the data. Thanks in advance.
Controller
public function getLecture($id)
{
$lectureID = student::select('lecture_id_FK')->where('student_id',$id)->first();
$lectureDATA = lecture::where('lecture_id',$lectureID)->first();
return $lectureDATA;
}
you can try two ways
public function getLecture($id)
{
## way 1
$lectureID = student::where('student_id',$id)->value('lecture_id_FK');
$lectureDATA = lecture::where('lecture_id',$lectureID)->first();
## way 2
$lectureID = student::where('student_id',$id)->first();
$lectureDATA = lecture::where('lecture_id',$lectureID->lecture_id_FK)->first();
return $lectureDATA;
}
before check what inside $lectureID:
public function getLecture($id)
{
$lectureID = student::select('lecture_id_FK')->where('student_id',$id)->first();
dd($lectureID);//I believe inside will be object with lecture_id_FK
//then just
$lectureDATA = lecture::where('lecture_id',$lectureID->lecture_id_FK)->first();
return $lectureDATA;
}
Recommended way to do it:
In Student model class ( recommend use capital S )
class student
{
public function lecture(){
return $this->hasOne('App\lecture','lecture_id_FK','lecture_id');
}
}
then just load studen with lecture like this
$student = studend::with('lecture')->find($id);
$lecture = $student->lecture;

How to create a class that will return an array or single item?

I am writing a class that I would like to be able to call later and have it return an array of values but it is returning only one.
I would like to be able to use my class like this. If I specify one user id new Blog([10]) then it shouldn't return an array but only one instance. If I specify more than one user id then it should return an array of items.
I am trying to create something similar to how Laravel works where you can say $posts = Posts::all(); or $posts = Post::where('id', 10)->first(); and in the first one it would return an array of all posts and in second it would return only one.
Example usage:
// Get one user's blog
$blog = new Blog([10]); // specify user ids
echo $blog->user->name; // Jane Smith
echo $blog->posts->title; // How to draw
echo $blog->posts->body; // In this post, I will teach you...
echo $blog->posts->created; // 2018-12-01
echo $blog->theme; // light/dark/other
echo $blog->is_awesome; // no
// Get blogs for users - 10, 20, 30
$blogs = new Blog([10, 20, 30]); // specify user ids
foreach ($blogs as $blog) {
echo $blog->user->name; // John Doe
echo $blog->posts->title; // 10 ways to live
echo $blog->posts->body; // Hello, in this post I will..
echo $blog->posts->created; // 2018-12-31
echo $blog->theme; // light/dark/other
echo $blog->is_awesome; // yes
}
My class
Class Blog
{
public $users;
public $posts;
public $comments;
public $theme;
public $is_awesome;
function __construct($users)
{
$this->users = new stdClass();
$this->users->id = $users; // array of ids
foreach ($this->users as $user) {
$this->user->name = self::getUsername($user->id) // John
$this->posts = self::getPosts($user->id); // array of posts
$this->comments = self::getComments($user->id); // array of comments
$this->theme = self::getTheme($user->id); // light/dark/other
if ($this->theme == 'dark') {
$this->is_awesome = 'yes';
} else {
$this->is_awesome = 'no';
}
}
}
}
I understand why you're trying to do, and since you asked another way, here it is. One of the approaches is to write a static method to retrieve yours blogs:
class Blog {
public static function fetchBlogsByIds() {
// [...]
}
// [...]
}
Then you call the method this way:
$blogs = Blog::fetchBlogsByIds(ids) {
$blogs = array();
foreach($ids as $id) {
$blogs[] = new Blog($id); // appending a new Blog entry
}
return $blogs;
}
You could also write a collection class named, for example BlogCollection and provide to it a constructor relying on an array of ids.
class BlogCollection {
// Builds the collection by the ids
function __construct(ids) {
// [...] similar implementation as fetchBlogsByIds() above
}
// [...]
}
Then you can retrieve your blogs this way:
blogs = new BlogCollection([10, 11]);
If you want to use foreach with your custom collection, you can make it implementing Traversable or Iterator.

Parameters to a class constructor function

I'm trying to adapt a class of mine that handles tags for events stored in a JSON file. You can create tags, delete them, restore them, view them, etc. In the code below for this library you can see that I retrieve the array from the file during the constructor function so I use it and manipulate it throughout my classes' functions.
class tagHandler {
private $tagsFile = "/home/thomassm/public_html/functions/php/tags.json";
private $LstTags;
private $LstReturn;
function __construct() {
$this->LstTags = array();
if(!file_exists ($this->tagsFile)){
$fHND = fopen($this->tagsFile, "w");
$tmpArray = array(array("EID","EName","EColor", "EDel"));
fwrite($fHND, json_encode($tmpArray));
fclose($fHND);
}
$encodedInput = file ($this->tagsFile);
$this->LstTags = json_decode($encodedInput[0], true);
if(!$this->LstTags) $this->LstTags = array();
}
function __destruct(){
$this->update();
}
public function update(){
$this->LstTags = array_values($this->LstTags);
$fHND = fopen($this->tagsFile, "w");
fwrite($fHND, json_encode($this->LstTags));
fclose($fHND);
//empty memory region
$this->LstTags = array();
$encodedInput = file ($this->tagsFile);
$this->LstTags = json_decode($encodedInput[0], true);
}
//More functions that use the collected array here.
I am trying to adapt the class to deal with people signed up to my events. Each event has a record in my database that will store a field for an array of males who sign up and females who sign up. I wish for the constructor class to get the arrays(s) from the record so they can be manipulated like the previous class. The issue is to get the array I have to search the DB for a record with the Event ID (EID) and that will require a variable passed to the constructor function. To make things worse, this parameter has to be able to change in a loop. For example, the page listing all the events will have to use this class in a loop going through each record, so it can retrieve the array to manipulate it and then show it in a table / fullcalendar before repeating the process to get the next event. I have put the code I have so far below. Its not complete (some variables haven't been renamed to male and female, etc) and may be completely wrong, but it will give you a base to explain from.
class signupHandler {
private $LstMaleS;
private $LstFemaleS;
private $LstReturn;
function __construct($IntEID) {
$this->LstTags = array();
$StrQuery = "SELECT MaleS, FemaleS FROM tblEvents WHERE EID = ?";
if ($statement = TF_Core::$MySQLi->DB->prepare($StrQuery)) {
$statement->bind_param('s',$IntEID);
$statement->execute ();
$results = $statement->get_result ();
}
$this->LstTags = json_decode($encodedInput[0], true);
if(!$this->LstTags) $this->LstTags = array();
}
Thanks,
Tom
function decodeNames($StrNames){
$this->LstNames = array();
$this->LstNames = json_decode($StrNames, true);
if(!$this->LstNames) $this->LstNames = array();
$this->LstNames = array_values($this->LstNames);
}
function update(){
$this->LstNames = array_values($this->LstNames);
return json_encode($this->LstNames);
}
public function addSignUp($StrNames, $StrUsername, $StrStatus){
$this->decodeNames($StrNames);
$BlnPresent = false;
for($i = 0; $i < count($this->LstNames); $i++){
if($this->LstNames[$i][0] == $StrUsername){
$this->LstNames[$i][1] = $StrStatus;
$BlnPresent = true;
}
}
if($BlnPresent == false){
array_push($this->LstNames, array($StrUsername, $StrStatus, date("Y-m-d H:i:s")));
}
return $this->update();
}
I have decided to pass the encoded JSON array to the class each time I call a function from it. Before every function it is decoded and turned into an array and at the end it is then re-encoded and returned back to the file calling it. Now I no longer have any constructor or destruct functions.

Getting table object(App_Model_TableName) as fetch result (Zend Framework)

Right now, I'd wrote a function in my model as:
public function getRowsByZipCode($zip)
{
// SQL to get all the rows with the given zip code
$stmt = $this -> getAdapter()
-> query( "SELECT *
FROM
table_name
WHERE
table_name.status = 1 AND
table_name.zip={$zip}");
$resultRows = $stmt->fetchAll();
// -------------------------------------------------------- //
// Convert result set to an array of objects
$resultObjects = array();
// If there is atleast one row found in DB
if(count($resultRows) > 0)
{
// Loop throguh all the rows in the resultset
foreach($resultRows as $resultRow) {
// Create table row and fill it with the details got from DB
$h = $this->createRow();
$h->setFromArray($resultRow);
// Add to the array
$resultObjects[] = $h;
}
}
return $resultObjects;
// -------------------------------------------------------- //
}
Which is working perfectly as I needed. And it is returning me an array that contains the tables row objects(App_Model_TableName Objects), which will be used later for further operations like save and delete etc.
What I really want is to remove the code that loop through the rows I got from the result set and converting each row to an object of App_Model_TableName that I'd wrote inside the comments // --- //.
Thanks in advance.
Firstly, I am assuming you are using PDO.
Try the following
class App_Model_TableName
{
public $status;
public $zip;
// public $other_column;
}
class YourClass
{
protected function getAdapter()
{
// Do adapter stuffs
}
public function query($query, array $param)
{
// When Using PDO always use prepare and execute when you pass in a variable
// This will help prevent SQL injection
$stmt = $this->getAdapter()->prepare($query);
return $query->execute($param);
}
/**
* #return App_Model_TableName[]
*/
public function getRowsByZipCode($zip)
{
// SQL to get all the rows with the given zip code
// This way will help prevent SQL injection
$query = "SELECT * FROM table_name WHERE table_name.status = 1 AND table_name.zip = :zip";
$qData = array(':zip' => $zip);
$results = $this->query($query, $qData);
return $results->fetchAll(PDO::FETCH_CLASS, 'App_Model_TableName');
}
}
Calling YourClass::getRowsByZipCode() will then return you an array of App_Model_TableName objects. You can then access them like:
$data = $instance_of_yourclass->getRowsByZipCode(12345);
foreach ($data as $row)
{
echo $row->zip;
echo $row->do_stuff();
}
All these awesome functions I found on:
http://php.net/manual/en/pdostatement.fetchall.php
http://php.net/manual/en/pdostatement.execute.php
Disclaimer: this code was not tested :(
Be cool but stay warm
Finally, I had found the solution:
public function getRowsByZipCode($zip)
{
// SQL to get all the rows with the given zip code
$stmt = $this -> getAdapter()
-> query( "SELECT *
FROM
table_name
WHERE
table_name.status = 1 AND
table_name.zip={$zip}");
$resultObjects= array();
while($data = $stmt->fetch())
{
$h = $this->createRow();
$h->setFromArray($data);
// Add to array
$resultObjects[] = $h;;
}
return $resultObjects;
}
I had removed the code that do the fetchAll() and loop through each row in the resultset. Now, I am taking each row from the resultset and creating an row of App_Model_TableName object using the data we got from the resultset.
Working perfectly for me.

Is there a better way of accessing and storing only required class properties

If I want to get a customer's email address from a database, the following is bad, because $row will contain an element for every single field in the customer table:
$result = mysqli_query ('SELECT * FROM customer WHERE custid = 1');
$row = mysqli_fetch_array ($result, MYSQLI_ASSOC);
This is considered better, because $row will contain a single element for the email address, which is all we need:
$result = mysqli_query ('SELECT email FROM customer WHERE custid = 1');
$row = mysqli_fetch_array ($result, MYSQLI_ASSOC);
I am trying to apply the same logic to objects. If a "customer" object has say 50 properties/fields, is it common to populate all 50 properties when you only need to access one?
Below is a basic example of a customer class and object which is resource hungry if all we want to do is get a customer's email address, and not all their other details (in this example a "customer" object has 5 properties but in reality there could be many more):
class Customer {
private $custid;
private $firstname;
private $lastname;
private $email;
private $dateadded;
public function getCustomer ($id) {
$result = mysql_queryi ('SELECT * FROM customer WHERE custid = ' . $id);
$row = mysqli_fetch_array ($result, MYSQLI_ASSOC);
foreach ($row as $key => $value) {
if (isset ($this->$key)) {
$this->$key = $value;
}
}
}
}
$customer = new Customer ();
$customer->getCustomer (1); // All I wanted is the email address, but now I have everything :-(
You could make a second argument to your getCustomer function that accepts an array of fields to query
public function getCustomer ($id, $fields=array('*')) {
$fields = implode(',', $fields);
$result = mysql_queryi("SELECT {$fields} FROM customer WHERE ...");
// ...
Usage
// get entire customer
$customer->getCustomer(1);
// just get the email field
$customer->getCustomer(1, array('email'));
// get full name
$customer->getCustomer(1, array('firstname', 'lastname'));
Bonus:
I'd recommend storing your fields a little differently in your model
class Customer
private $_data;
public function getCustomer($id, $fields=array('*')) {
// ...
}
// PHP magic set method
// calling $this->foo = 'bar' results in $this->_data['foo'] = 'bar'
public function __set($key, $value) {
return $this->_data[$key] = $value;
}
// PHP magic get method
// calling $this->foo results in $this->_data['foo']
public function __get($key) {
return array_key_exists($key, $this->_data)
? $this->_data[$key]
: null
;
}
}
This way you can get rid of all the statically defined instance variables; e.g., private $custid;, private $firstname;, private ...
Instead, all fields will be stored in $this->_data private associative array.
What's sweet about this is you don't even have to change the way your getCustomer function is written.
Learn more about PHP magic methods
You can create a get Email address method:
public function getCustomerEmail ($id) {
$result = mysql_queryi ('SELECT email FROM customer WHERE custid = ' . (int)$id);
$row = mysqli_fetch_array ($result, MYSQLI_ASSOC);
foreach ($row as $key => $value) {
if (isset ($this->$key)) {
$this->$key = $value;
}
}
}
PS: don't forget to sanitize your variables before using them in a query
First...
You really should seperate the logic for fetching customer objects from the actuall object... I would suggest looking at the repository/facade patterns for examples.
Eg. CustomerCollectionInstance->getCustomer($id) returns a Customer Entity.
Your example is extremely simple so the difference from pulling just the e-mail and all thoes fields should be insignificant. If your objects are massively, say a customer who could have 500 orders. The orders should be separated into there own objects, and when the entity object is assembled thoes heavy objects should not be loaded but have proxy objects in their place that when accessed then query the db for that data.
eg.
You call getCustomer on the CustomerCollection...
CustomerCollection returns a CustomerEntity with basic data loaded and the customerOrders is set with a CustomerOrderCollectionProxy object..
You call CustomerEntity->getOrders() which return the CustomerOrderCollectionProxy object
Once you make a call to the CustomerOrderCollectionProxy it will first check if it has loaded the required data from the DB... if not it will then assemble a real CustomerOrderCollection and delegate all calls to that object that now has the date you need.
See the proxy pattern for an example.

Categories