I want to Retrive Downtree of my current Tree - php

I have the below tree with present data. I want tree below 103 only.
+----------------+----------------+
| child | parent |
+----------------+----------------+
| 216 | 103 |
| 217 | 216 |
| 88 | 216 |
| 102 | NULL |
| 103 | 102 |
| 104 | 102 |
+----------------+----------------+
the output should be a below format
102
/ \
103 104
/
216
/ \
217 218
from this
103
/
216
/ \
217 218
I need this in Mysql
I tried to get 103 child, then I get 216. again I tried child of 216. and so on in my MYSQL until end. How I get, the tree End?

Below is the code which you can alter as per the requirement.
The sample code can be used in Laravel as a Helper function to get all the child nodes.
class UserUtility
{
public static function children_ids($id)
{
$children = UserUtility::flat_children($id);
return !empty($children) ? array_column($children, 'id') : array();
}
public static function flat_children($id)
{
$children = UserUtility::get_immediate_children($id, $with_trashed, true, $role_id);
if (!empty($children)) {
foreach ($children as $child) {
$container[] = $child;
$container = UserUtility::flat_children($child['id'], $with_trashed, $container, $role_id);
}
}
return $container;
}
public static function get_immediate_children($id)
{
$children = User::withoutGlobalScopes()->where('parent_id', $id)->get(); // get the children data from DB
$children = $as_array && !is_null($children) ? $children->toArray() : array();
return $children;
}
}

Related

Applying if-else condition to export selective records using PhpExcel

I need to export only those records whose column satisfies defined value.
Eg.
if(null !== ($this->f3->get('SESSION.userStatus')))
{
$userStatus = $this->f3->get('SESSION.userStatus');
}
This is how I tried to set cell values depending on set value:
$rowID = 5;
foreach ($results as $result)
{
if($result['status'] == $userStatus)
{
$objPHPExcel->getActiveSheet()->setCellValue('A'.$rowID, $result['fullname']);
$objPHPExcel->getActiveSheet()->setCellValue('B'.$rowID, $result['checkin_date']);
}
else
{
$objPHPExcel->getActiveSheet()->removeRow($rowID);
}
$rowID++;
}
The file is exported with only those records that have defined "status" value.
But the problem is that rows whose criteria doesn't meet are filled with spaces and still occupies rows.
Here is how output looks like:
A | B | C | D
1 | | |
.
.
174 | | |
175 | | |
176 | | |
177 | | |
178 John | 2014| xyz | dfdf
179 Jack | 2015| jkl | dfdf
180 | | |
.
.
How can I fix it to get records starting with top row?
Eg.
1 | John | 2014 | xyz | dfdf
2 | Jack | 2015 | jkl | dfds
between
}
$rowID++;
put this
else
{
$objPHPExcel->getActiveSheet()->removeRow($rowID);
}
That will delete your blank rows.
Note, that you start with row 5 for some reason and do not test for max rows. Your code will still need some fixing up

removeRow() not removing rows as expected in phpExcel

I tried removing blank rows [actually rows that doesn't meet criteria].
This is what I tried:
if(null !== ($this->f3->get('SESSION.userStatus')))
{
$userStatus = $this->f3->get('SESSION.userStatus');
}
$rowID = 5;
foreach ($results as $result)
{
if($result['status'] == $userStatus)
{
$objPHPExcel->getActiveSheet()->setCellValue('A'.$rowID, $result['fullname']);
$objPHPExcel->getActiveSheet()->setCellValue('B'.$rowID, $result['checkin_date']);
}
else
{
$objPHPExcel->getActiveSheet()->removeRow($rowID);
}
$rowID++;
}
But still I'm getting blank rows:
A | B | C | D
1 | | |
.
.
174 | | |
175 | | |
176 | | |
177 | | |
178 John | 2014| xyz | dfdf
179 Jack | 2015| jkl | dfdf
180 | | |
.
.
How do I get rid of those empty rows? Row numbers don't really matter, all I need to do is get rid of those blank rows. Please help me with this...Thanks.
You are still incrementing rowID that's why you've got empty rows
if(null !== ($this->f3->get('SESSION.userStatus')))
{
$userStatus = $this->f3->get('SESSION.userStatus');
}
$rowID = 5;
foreach ($results as $result)
{
if($result['status'] == $userStatus)
{
$objPHPExcel->getActiveSheet()->setCellValue('A'.$rowID, $result['fullname']);
$objPHPExcel->getActiveSheet()->setCellValue('B'.$rowID, $result['checkin_date']);
}
else
{
$objPHPExcel->getActiveSheet()->removeRow($rowID);
continue;
}
$rowID++;
}

Duplicate Data Stop in MySQL

I have a table below :
+-----+-------+------+------------+
| ID | RefID | Type | EventTime |
+-----+-------+------+------------+
| 101 | 228 | 1 | 1437195633 |
| 102 | 228 | 5 | 1437195633 |
| 103 | 228 | 1 | 1437195633 |
| 104 | 228 | 1 | 1437195442 |
| 105 | 228 | 1 | 1437195442 |
| 106 | 228 | 5 | 1437195442 |
| 107 | 228 | 1 | 1437165634 |
| 108 | 228 | 5 | 1437165442 |
| 109 | 228 | 1 | 1437165634 |
| 110 | 228 | 5 | 1437165442 |
+-----+-------+------+------------+
In that I want to stop inserting duplicate data based on the columns RefID,Type,EventTime only when value of Type = 1.
In the above table ID pair is duplicate (101,103), (104,105), (107,109).
If now I will insert another data say :
INSERT INTO table VALUES('',228,1,1437165634);
Then it should not insert. I am checking while inserting into that table but that is not working as I have checked at the same time 2 insert query is happening, I need to stop it using UNIQUE key constraints.
You need change DB architecture. Add table with unique index by RefId, here you will write record with Type "1". In your Yii model in method beforesave check your Type if is 1 to write in added table otherwise write to old table. And you need change beforefind method
And I'm sorry for my english
Please try:
public function unique($attribute, $params)
{
if(!empty($model_name)){
$this->addError('RefID', 'RefID already exists! Please choose a different one');
return true;}
}
as a custom function in before save. and call it for the fields you want in the rule. I'm showing you the template for a single field refID
I have solved it by using trigger as below :
DB Trigger
delimiter $$
drop trigger if exists stop_duplicate $$
create trigger stop_duplicate before insert on table
for each row
begin
set #found := false;
if new.Type = 1 then
SELECT
TRUE
INTO #found FROM
table
WHERE
RefID = new.RefID AND EventTime= new.EventTime AND Type= new.Type;
if #found then
signal sqlstate '23000' set message_text = 'CUSTOM_MSG_DUPLICATE';
end if;
end if;
end $$
delimiter ;
Yii Model Code
public function save($runValidation = true, $attributes = null) {
Yii::log(__METHOD__.":: Start ", 'info');
try {
return parent::save();
} catch (Exception $e) {
$errorInfo = $e instanceof PDOException ? $e->errorInfo : null;
$message = $e->getMessage();
Yii::log(__METHOD__ . ": errorcode :{$e->getCode()}, errormessage:{$message} ", 'info');
// Added for handling duplicate entry issue for index
if ((int) $e->getCode() === 23000 && strpos($message, 'CUSTOM_MSG_DUPLICATE') !== false) {
return false;
}
throw new CDbException(Yii::t('yii', 'CDbCommand failed to execute the SQL statement: {error}', array('{error}' => $message)), (int) $e->getCode(), $errorInfo);
}
}

Excel generation from database using PEAR

I have a mysql table like this
product | date | price
mobile | jan-14| 150
laptop | jan-14| 480
mobile | feb-14| 172
laptop | feb-14| 389
By using below code i got an output like this
product |jan 14 |feb 14|
mobile | 150 | 172 |
laptop | 480 | 389 |
My PHP code(PEAR)
<?php writer, query fetching, worksheet,workbook, etc..on here
$product=array();
$date1=array();
$price=array();
while($rr=mysql_fetch_array($result))
{
$col=0;
$product[$rr['product']]=$rr['product'];
$date1[$rr['date']]=$rr['date'];
$price[$rr['prodcut']][$rr['date']]=$rr['price'];
}
$row=1;
$col=1;
foreach($date1 as $tkey=>$t)
{
$worksheet->write($row,$col++,$t);
}
$row=2;
foreach($product as $dkey=>$d)
{
$col=0;
$worksheet->write($row,$col++,$d);
foreach($date1 as $tkey=>$t)
{
$worksheet->write($row,$col++,$price[$d][$t]);
}
$row++;
}
$workbook->close();
?>
But,I need an output along with total of product wise and date wise like below,
product |jan 14 |feb 14|Prod total
mobile | 150 | 172 | 322
laptop | 480 | 389 | 869
date total| 630 | 561 |
could anyone help me? Thanks advance.
Would be like this:
foreach($product as $dkey=>$d)
{
$col=0;
$worksheet->write($row,$col++,$d);
$total = 0;
foreach($date1 as $tkey=>$t)
{
$worksheet->write($row,$col++,$price[$d][$t]);
$total += $price[$d][$t];
}
$worksheet->write($row,$col++,$total);
$row++;
}

SQL Query and PHP manipulation with Nested Set Model

I was reading this article, http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/.
I wanted to give a simple example and then ask you how do I get the desired result? So here is the example:
+---------+-----------------------------+
| product_id | product_name |
+---------+-----------------------------+
| 1 | Example Product |
+---------+-----------------------------+
+---------+-----------------------------+
| product_id | category_id |
+---------+-----------------------------+
| 1 | 2 |
| 1 | 4 |
+---------+-----------------------------+
+-------------+--------------------+------+------+
| category_id | name | lft | rgt |
+-------------+--------------------+------+------+
| 1 | Electronics | 1 | 8 |
| 2 | Televisions | 2 | 3 |
| 3 | Portable Electronics | 4 | 7 |
| 4 | CD Players | 5 | 6 |
+-------------+--------------------+------+------+
I want to be able to display the following result in HTML after querying and then manipulating the data in PHP:
"Example Product" Categories:
Electronics
Televisions
Portable Electronics
CD Players
Can you help walk me through the query and manipulation in PHP to achieve this result?
Some specifics to think about:
Notice how both categories are under Electronics, but "Electronics" appears only once here, displaying each of the subcategories it belongs to below
The result should eventually be a PHP multi-dimensional array with the category containing an array of sub-categories and each sub-category containing an array of sub-subcategories if they exist.
I imagine printing the depth will be very important for constructing the right tree in HTML.
I thought this was a nice challenge .. here's my solution:
Basically: read a node, then all following nodes with a rgt smaller than your rgt are your children, do this recursively.
I've used a peek/consume to read from mysql like you normally would.
The script will break or loop if the query gives no results, or if the data-set is broken.
class NestedNodeReader {
private $mysql_result;
private $peeked = false;
private $last_peek;
public function __construct($mysql_result) {
$this->mysql_result = $mysql_result;
}
public function getTree() {
$root = $this->consume();
$root["children"] = $this->getSubTree($root["rgt"]);
return $root;
}
private function getSubTree($stop_at) {
$nodes = array();
$node = $this->peek();
while ($node["rgt"] < $stop_at) {
$node = $this->consume();
$node["children"] = $this->getSubTree($node["rgt"]);
$nodes[] = $node;
$node = $this->peek();
if (false === $node) {
break;
}
}
return $nodes;
}
private function peek() {
if (false === $this->peeked) {
$this->peeked = true;
$this->last_peek = mysql_fetch_assoc($this->mysql_result);
}
return $this->last_peek;
}
private function consume() {
if (false === $this->peeked) {
return mysql_fetch_assoc($this->mysql_result);
} else {
$this->peeked = false;
return $this->last_peek;
}
}
}
$query = "SELECT node.name, node.lft, node.rgt
FROM nested_category AS node,
nested_category AS parent
WHERE node.lft BETWEEN parent.lft AND parent.rgt
AND parent.name = 'ELECTRONICS'
ORDER BY node.lft;"
$mysql_result = mysql_query($query);
$nnr = new NestedNodeReader($mysql_result);
print_r($nnr->getTree());

Categories