CakePHP - Associate item status code to status txt - php

I usually save itens status within a code (let's save I have the table: students, to save studentes status, I use the field (students.status)).
But, Everytime I list Users I will not shown the status code (1 or 0 for example). I need show: Registered or Cancelled.
I can simply check it when I list, but, let's say I need do it a lot of times.
Is there anything than can help me doing it? would save a lot of work, every page I'll list the user, or even when I add/edit him or a drop-down menu that should come with those items.
I've checked the models associations, but the solution that I've found works if I have another table with user status saved for example (I honestly don't wanna create it).
Thanks.

This describes how to do what you want: http://www.dereuromark.de/2010/06/24/static-enums-or-semihardcoded-attributes/

If the status can be registered or cancelled then you can use enum data type in your table schema.
You can get the list of status from enum data type for populating drop down like this.
$status = $this->Model->getEnumValues('status');
Before this you need to add following code in your appModel.php
function getEnumValues($columnName=null)
{
if ($columnName==null) { return array(); } //no field specified
//Get the name of the table
$db =& ConnectionManager::getDataSource($this->useDbConfig);
$tableName = $db->fullTableName($this, false);
//Get the values for the specified column (database and version specific, needs testing)
$result = $this->query("SHOW COLUMNS FROM {$tableName} LIKE '{$columnName}'");
//figure out where in the result our Types are (this varies between mysql versions)
$types = null;
if ( isset( $result[0]['COLUMNS']['Type'] ) ) { $types = $result[0]['COLUMNS']['Type']; } //MySQL 5
elseif ( isset( $result[0][0]['Type'] ) ) { $types = $result[0][0]['Type']; } //MySQL 4
else { return array(); } //types return not accounted for
//Get the values
$values = explode("','", preg_replace("/(enum)\('(.+?)'\)/","\\2", $types) );
//explode doesn't do assoc arrays, but cake needs an assoc to assign values
$assoc_values = array();
foreach ( $values as $value ) {
//leave the call to humanize if you want it to look pretty
$assoc_values[$value] = Inflector::humanize($value);
}
return $assoc_values;
}
I hope this will work for you. Thanks

I ended up creating a Helper function for that (not sure if the best way, it's been working fine)
MyHelper.php
class MyHelper extends AppHelper {
public $helpers = array();
public $list = array(0 => 'Cancelled', 1 => 'Registered');
public function __construct(View $View, $settings = array()) {
parent::__construct($View, $settings);
}
public function beforeRender($viewFile) {
}
public function afterRender($viewFile) {
}
public function beforeLayout($viewLayout) {
}
public function afterLayout($viewLayout) {
}
public function translate($id){
return $this->list[$id];
}
}
In view.ctp, intestead of showing the item ID, I just call the translate function, returning the proper name.
To create drop-down menus, it's just call the array list in select options.
<?php
echo "User Status: " . $this->My->translate($this->User->status);
echo $this->Form->input('tipo', array('type' => 'select', 'options' => $this->My->list));
?>
I think I should have used enum too, and using the functions specified, I would have success too.
Thanks for the helps.

You might want to look at model associations. In your case, I would have a students table and a student_statuses table that contains an ID and a status name. Then, when finding students, you can also include their corresponding StudentStatus row.
This relationship would look as follows:
<?php
class Student extends AppModel {
public $belongsTo = array('StudentStatus');
}
<?php
class StudentStatus extends AppModel {
public $hasMany = array('Student');
}
Then when finding students…
<?php
class StudentsController extends AppController {
public function index() {
$this->set('students', $this->Student->find('all'));
}
}
You will get a result like this:
Array
(
[0] => Array
(
[Student] => Array
(
[id] => 1
[name] => Martin Bean
[student_status_id] => 1
[created] => 2013-09-29 21:12:42
[modified] => 2013-09-29 21:12:42
)
[StudentStatus] => Array
(
[0] => Array
(
[id] => 1
[name] => Approved
[created] => 2013-09-23 18:26:06
[modified] => 2013-10-01 18:53:16
)
)
)
)
So you can just print the students’ status in your view as follows:
<?php foreach ($students as $student): ?>
<p>
<?php echo h($student['Student']['name']); ?>
(<?php echo h($student['StudentStatus']['name']); ?>)
</p>
<?php endforeach; ?>
You say you don’t want to create a table for statuses, but the reason you’re having issues is because it’s how relational databases work and also the convention. You’ll save yourself a lot of headaches by doing so, and it’s also extensible if you decide you need to add additional statuses in the future. You may not think you do now, but believe me: one day you will.

Related

Accumulate strings and array values into an array as a class property via method

I have a class with method add() that accepts strings and arrays. I need to have an array with all users, but I cannot seem to get it. All I get is multiple arrays with all users. How could I merge those arrays into one?
class Users {
function add($stringOrArray) {
$arr = array();
if(is_array($stringOrArray)) {
$arr = $stringOrArray;
} else if(is_string($stringOrArray)) {
$arr[] = $stringOrArray;
} else {
echo('errrrror');
}
print_r($arr);
}
When I use this test:
public function testOne() {
$users = new Users();
$users->add('Terrell Irving');
$users->add('Magdalen Sara Tanner');
$users->add('Chad Niles');
$users->add(['Mervin Spearing', 'Dean Willoughby', 'David Prescott']);
This is what I get, multiple arrays but I need one array.
Array
(
[0] => Terrell Irving
)
Array
(
[0] => Magdalen Sara Tanner
)
Array
(
[0] => Chad Niles
)
Array
(
[0] => Mervin Spearing
[1] => Dean Willoughby
[2] => David Prescott
)
You can cut a lot of unnecessary bloat from your method.
You can cast ALL incoming data to array type explicitly. This will convert a string into an array containing a single element. If the variable is already an array, nothing will change about the value.
Use the spread operator (...) to perform a variadic push into the class property.
Code: (Demo)
class Users
{
public $listOfUsers = [];
function add($stringOrArray): void
{
array_push($this->listOfUsers, ...(array)$stringOrArray);
}
}
$users = new Users;
$users->add('Terrell Irving');
$users->add(['Magdalen Sara Tanner', 'Chad Niles']);
$users->add(['Mervin Spearing']);
var_export($users->listOfUsers);
Output:
array (
0 => 'Terrell Irving',
1 => 'Magdalen Sara Tanner',
2 => 'Chad Niles',
3 => 'Mervin Spearing',
)
All you need is to store the added users in a class property, for example $listOfUsers.
If adding the array you use the array_merge() function otherwise just add new user at the end of indexed array.
<?php
class Users {
// here will be all the users stored
public $listOfUsers = array();
function add($stringOrArray) {
//$arr = array();
if(is_array($stringOrArray)) {
// merge two arrays - could create duplicate records
$this->listOfUsers = array_merge($this->listOfUsers, $stringOrArray);
} else if(is_string($stringOrArray)) {
// simply add new item into the array
$this->listOfUsers[] = $stringOrArray;
} else {
echo('errrrror');
}
print_r($this->listOfUsers);
}
}
In your example you are storing the data locally within the method add() and it is not kept for future usage. This behavior is corrected using the class property $listOfUsers that can be accesed using $this->listOfUsers within the class object and if needed outside of the class.

How can I convert the array to a string variable in php codeigniter?

I am new to Codeigniter and want to display my state_name which I believe in an array, but I want the first element in that array to be in a variable and be displayed
I am getting the output as: Array ( [0] => stdClass Object ( [state_name] => XYZ state ) )
the output I want is just XYZ state
My controller goes like this:
public function downloadd()
{
$this->load->model('New_model');
$state_id=$this->input->post('state'); //gets me state_id from my view
$state_name = $this->New_model->getStatename($state_id); //gets me state_name in form of above output
print_r($state_name[0]);
exit;
}
And here is my model code:
public function getStatename($state_id) {
$this->db->select('state_name');
$this->db->where('state_id',$state_id);
$state_name=$this->db->get('states')->result();
return $state_name; //geting users data from db in result array
}
Please tell me where am I going wrong, Thanks for any contribution in advance :)
Just edit your last two lines of code in your model as follows:
$ans= $this->db->get('states')->row_array();
return $ans['state_name'];
This shall do the needful.
The result value is a array so you should use row_array to get first row and check if it exists:
public function getStatename($state_id) {
$this->db->select('state_name');
$this->db->where('state_id',$state_id);
$row = $this->db->get('states')->row_array();
if($row)
return $row['state_name'];
else {
//should handle the error since data not found
}
}

Query returns content from previous functions

I have a Chat.php file containing everything query-related. Then there is a Core.php containing connection to database and basic functions used in Chat.php like "query" and "rows" which processes the "query" into array.
In Chat.php there are two functions, the second one printing content of the first when using print_r($this->rows());. checkForLastMessage() is supposed to check one table to see if there are new messages to be pulled from another table with function getNewMessages().
This is how it looks like:
Core.php
<?php
class Core
{
...
public function query($sql)
{
$this->result = $this->db->query($sql);
}
public function rows()
{
for($x = 1; $x <= $this->db->affected_rows; $x++)
{
$this->rows[] = $this->result->fetch_assoc();
}
return $this->rows;
}
}
Chat.php
<?php
class Chat extends Core
{
public function checkForLatestMessage($chatid, $iam)
{
$userinchat='for'.$iam;
$this->query("SELECT anonchat.$userinchat FROM anonchat WHERE anonchat.chatid=$chatid");
$printarray = Array();
$printaray = '';
foreach( $this->rows() as $id )
{
$printarray[] = $id[$userinchat];
}
if($printarray[0] != '')
{
$this->getNewMessages($chatid, $printarray[0]);
}
}
public function getNewMessages($chatid, $requiredMessages)
{
$this->query("SELECT anonmessage.content, anonmessage.timeposted FROM anonmessage WHERE anonmessage.messageid IN ($requiredMessages) ORDER BY anonmessage.timeposted ASC");
print_r($this->rows());
}
The last print_r contains elements from the previous function. I don't know why that is.
Edit. This is the output:
Array ( [0] => Array ( [for1] => 2,4,6 ) [1] => Array ( [content] =>
Message 2 [timeposted] => 2017-08-04 16:12:34 ) [2] => Array (
[content] => Message 4 [timeposted] => 2017-08-04 16:12:48 ) [3] =>
Array ( [content] => Message 6 [timeposted] => 2017-08-04 16:13:03 ) )
Element [0] of array (the one with "for1") is remaining from previous function.
To answer your question, you're initializing the class property $this->rows in the first method and then the 2nd method is appending to it. You need to reset $this->rows before adding to it.
public function getNewMessages($chatid, $requiredMessages)
{
$this->rows = null;
$this->query("SELECT anonmessage...");
print_r($this->rows());
}
Or better yet, reset the variable in the query() method. That way you don't have to do it each time.
Please don't take offense when I say that this is a bad design.
You're trying to write your own DAL (Data Abstraction Layer). This is a very complicated task and there are already lots of implementations out there. The Core class is going to become massive, complicated, and unwieldy when you try to adapt it to a dozen other classes.
PHP only supports a single inheritance so right off the bat you shot your self in the foot because any class that needs DB interactions will have to extend Core and you won't be able to extend anything else.
Consider keeping things simple for now and let each method handle their own queries and DB interactions. Focus on major concepts like DRY, encapsulation and keeping your classes focused on their responsibility.
Ex. checkForLatestMessage() what is this supposed to do? It sounds like should check for messages and then return a boolean (true|false) but instead it is calling getNewMessages() which outputs some data.
I don't know enough about your application to really suggest something useful but this feels a bit better than the path you're heading down. Notice we're not inheriting from Core so you're free to inherit from something else. The methods are concise and do what they say. You'd probably also save a few lines of code this way and it's easier to read.
<?php
class Chat
{
public function hasNewMessages($chatid, $iam)
{
// Query using PDO properly
return (bool)$hasNewMessages;
}
public function getNewMessages($chatid, $requiredMessages)
{
// Query using PDO properly
// An array of data or objects
return $messages;
}
}
/******** Client Code ***********/
$chat = new Chat();
if ($chat->hasNewMessages()) {
foreach ($chat->getNewMessages($id, $required) as $message) {
// $message
}
}
Just some of my thoughts... good luck.

Associative array's loaded from database and display as 'columns'

I am trying to create an overview of product properties, for an invoice system.
So far, most things are comming together using classes and PDO.
I have the following issue.
In my class, i've created a function that builds my products array.
It loads some information from the database, to build this array.
This array, i want to use to display all the products i have selected:
$prod1 - $prod1Name - $prod1Descr - $prod1Price
$prod2 - $prod2name - $prod2Descr - $prod2Price
etc.
I figured that the Associative array would help me creating columns.
Though the problem is, that i do not understand a bit how to create multiple lines and columns this way.
I was thinking of something like:
$prod[1]["name"] - $prod[1]["descr"] - etc
Then to use this in a foreach loop to create as many new lines as required.
The only thing i could come up with is on my index.php (as shown below), cause using an index (the [1] defenition) does not seem to work the way i think it should be implemented.
For my understanding, i assigend the var in my class as an array, then redefine an array when loading the database information.
Could anyone tell me how i could try to solve this issue?
I have the following class:
<?
class Invoice{
var $vendorID;
var $product = array();
function product_array(){
global $db;
$query = $db->conn->prepare('
SELECT ProductName, ProductDescription, ProductDuration, ProductPriceInclVat, ProductPriceExclVat, ProductVatType
FROM products WHERE VendorID = :VendorID
');
$array = array (
'VendorID' => $this->vendorID
);
$query->execute($array);
$result = $query->fetchall();
if (empty($result)){
echo"Could not find any products matching your criteria.";
die;
} else {
foreach($result as $row) {
$this->product = array("Name" => $row['ProductName'],
"Description" => $row['ProductDescription'],
"Duration" => $row['ProductDuration'],
"PriceExclVat" => $row['ProductPriceExclVat'],
"PriceInclVat" => $row['ProductPriceInclVat'],
"VatType" => $row['ProductVatType']
);
}
}
}
}
?>
and then i have the following code on my index.php:
<?
$invoice = new Invoice();
foreach ($invoice->product as $key => $value){
echo $key . "<br>";
echo $value . "$value";
echo "<br>";
}
?>
When you are assigning the result arrays to the product property you are overwriting the array every time. You need to append to the array instead, so something like:
$this->product = array();
foreach($result as $row) {
$this->product[] = array(...);
}
Alternatively, you could just assign the results of fetchAll to the product property if you don't need to rename the field keys (or you could alias them in the SQL).
$query = $db->conn->prepare('
SELECT ProductName as Name,
ProductDescription as Description,
ProductDuration as Duration,
ProductPriceInclVat as PriceInclVat,
ProductPriceExclVat as PriceExclVat,
ProductVatType as VatType
FROM products WHERE VendorID = :VendorID
');
$array = array (
'VendorID' => $this->vendorID
);
$query->execute($array);
$product = $query->fetchall(PDO::FETCH_ASSOC);
The $product is now in the format you require.
After this you can avoid foreach loop in class invoice.
Other thing i noticed that you have made function product_array() which is not called,
so in index.php you are getting empty array (defined in class Invoice).
So in Invoice class it should be
$product = product_array()
and product_array function should return the value.

How to call function inside controller inside foreach loop with different parameters value

i am trying to call m custom function repeatedly with same or different parameters value,inside foreach loop parameters depending upon value to key provided my foreach.
foreach ($result as $r) {
if($r->marks1==null || $r->marks2==null)
{
echo $r->p_code;
$toUpdate=$this->getResult($username,$r->p_code);
print_r($toUpdate);
}
}
but when i am printing the latest query result i am getting $toUpdate get appended by latest parameter query.
Array
(
[query] => select * from `result` where (`studentid` = ?) and `studentid` = ? and `ccode` = ? and `a_no` = ? order by `date` desc limit 1
[bindings] => Array
(
[0] => XYZ
[1] => XYZ
[2] => course123code
[3] => 12321
)
[time] => 0.18
)
my user name getting same, while course code is get overrides while finding second result.
i want to get the result getResult() inside foreach loop so that it may give the related result for different parameters value.
public function getLatestResult($username,$course_code)
{
$user=new User;
$currentDetailOfUser=$this->userCurrentDetail($username);
$userdetail=json_decode($currentDetailOfUser,true);
$username =$userdetail['username'];
$studentid =$userdetail['userid'];
$studentBatch =$userdetail['batch'];
$programCode =$userdetail['programCode'];
$activeSemester =$userdetail['activesemester'];
$condition_key=array(
'studentid' =>$studentid
);
$getCurrentResult1 =$user->getDetail('student_result',$condition_key);
$getCurrentResult2 =$user->getDetail('student_result',$condition_key);
$resultAssessment1=$getCurrentResult1->where('studentid',$studentid)->where('course_code',$course_code)->where('assignment_no',1)->orderBy('date','Desc')->limit(1)->get();
$resultAssessment2=$getCurrentResult2->where('studentid',$studentid)->where('course_code',$course_code)->where('assignment_no',2)->orderBy('date','Desc')->limit(1)->get();
$recentResult=array_merge($resultAssessment1,$resultAssessment2);
return $recentResult;
}
This is a bad practice if you are fetching data from db inside the foreach loop.
BTW you can do this by keeping all new result in same array by index its some unique value, it will be look like this-
$toUpdate=array();
foreach ($result as $r) {
if($r->marks1==null || $r->marks2==null)
{
echo $r->p_code;
$toUpdate[$r->p_code]=$this->getResult($username,$r->p_code); // added $r->p_code as index to Array - $toUpdate
}
}
print_r($toUpdate); // this will give all the related result according your parameters
[UPDATE]
Try using unset($yourarray) for your next request these array will be new and they assign the new value each time -
public function getLatestResult($username,$course_code)
{
$user=new User;
$currentDetailOfUser=$this->userCurrentDetail($username);
$userdetail=json_decode($currentDetailOfUser,true);
$username =$userdetail['username'];
$studentid =$userdetail['userid'];
$studentBatch =$userdetail['batch'];
$programCode =$userdetail['programCode'];
$activeSemester =$userdetail['activesemester'];
$condition_key=array(
'studentid' =>$studentid
);
$getCurrentResult1 =$user->getDetail('student_result',$condition_key);
$getCurrentResult2 =$user->getDetail('student_result',$condition_key);
$resultAssessment1=$getCurrentResult1->where('studentid',$studentid)->where('course_code',$course_code)->where('assignment_no',1)->orderBy('date','Desc')->limit(1)->get();
$resultAssessment2=$getCurrentResult2->where('studentid',$studentid)->where('course_code',$course_code)->where('assignment_no',2)->orderBy('date','Desc')->limit(1)->get();
unset($currentDetailOfUser);
unset($userdetail);
unset($condition_key);
unset($recentResult);
$recentResult=array_merge($resultAssessment1,$resultAssessment2);
return $recentResult;
}
Hope this can help you.

Categories