how do I treat html in a loop when using MVC? - php

Can someone please show me how to do this basic thing using Zend Framework MVC?
I'm looping over the timestamp data and populating my table that way. i don't understand how I would pull my presentation HTML from this loop and stick it in the view? Any help would be greatly appreciated!
<table>
<?php
$day = date("j");
$month = date("m");
$year = date("Y");
$currentTimeStamp = strtotime("$year-$month-$day");
$numDays = date("t", $currentTimeStamp);
$counter = 0;
for($i = 1; $i < $numDays+1; $i++, $counter++)
{
$timeStamp = strtotime("$year-$month-$i");
if($i == 1)
{
// Workout when the first day of the month is
$firstDay = date("w", $timeStamp);
for($j = 0; $j < $firstDay; $j++, $counter++)
echo "<td> </td>";
}
if($counter % 7 == 0) {
echo "</tr><tr>";
}
echo "<td>" .$i . "</td>";
}
?>
</table>
I'm wanting to turn the above code into functions, but the HTML is throwing me off.

******Edited**** (mvc solution added)
Don't clutter your code with unnecessary functions, partials, etc. Why bother with HTML from the start, when you can create your data, then transform it into an HTML table? Here's the MVC sample (the following code suppose a one module project called 'default', modify accordingly if the project is module based) :
[listing 1] application/controller/IndexController.php
class IndexController extends Zend_Controller_Action {
public function indexAction() {
$this->view->calData = new Default_Model_Calendar('2010-07-17');
}
}
[listing 2] application/models/Calendar.php
class Default_Model_Calendar {
/* #var Zend_Date */
private $_date;
/* #param Zend_Date|string|int $date */
public function __construct($date) {
$this->_date = new Zend_Date($date);
}
/* #return Zend_Date */
public function getTime() {
return $this->_date;
}
public function getData() {
// normally, fetch data from Db
// array( day_of_month => event_html, ... )
return array(
1 => 'First day of month',
4 => '<span class="holiday">Independence Day</span>',
17 => '<img src="path/to/image.png" />'
//...
);
}
}
[lisging 3] application/view/scripts/index/index.phtml
echo $this->calendarTable($this->calData);
[listing 4] application/view/helpers/CalendarTable.php
class Default_View_Helper_CalendarTable extends Zend_View_Helper_Abstract {
private $_calData;
public function calendarTable($calData = null) {
if (null != $calData) {
$this->_calData = $calData;
}
return $this;
}
public function toString() {
$curDate = $this->_calDate->getTime();
$firstDay = clone $curDate(); // clone a copy to modify it safely
$firstDay->set(Zend_Date::DAY, 1);
$firstWeekDay = $firstDay->get(Zend_Date::WEEKDAY);
$numDays = $curDate->get(Zend_Date::MONTH_DAYS);
// start with an array of empty items for the first $firstweekDay of the month
$cal = array_fill(0, $firstweekDay, ' ');
// fill the rest of the array with the day number of the month using some data if provided
$calData = $this->_calData->getData();
for ($i=1; $i<=$numDays; $i++) {
$dayHtml = '<span class="day-of-month">' . $i . '</span>';
if (isset($calData[$i])) {
$dayHtml .= $calData[$i];
}
$cal[] = $dayHtml;
}
// pad the array with empty items for the remaining days of the month
//$cal = array_pad($cal, count($cal) + (count($cal) % 7) - 1, ' ');
$cal = array_pad($cal, 42, ' '); // OR a calendar has 42 cells in total...
// split the array in chunks (weeks)
$calTable = array_chunk($cal, 7);
// for each chunks, replace them with a string of cells
foreach ($calTable as & $row) {
$row = implode('</td><td>', $row);
}
// finalize $cal to create actual rows...
$calTable = implode('</td></tr><tr><td>', $calTable);
return '<table class="calendar"><tr><td>' . $calTable . '</td></tr></table>';
}
public function __toString() {
return $this->__toString();
}
}
With this code, you can even set exactly what you want within the $cal array before calling array_chunk on it. For example, $cal[] = $dayHtml . 'more';
This also follow true MVC as data (in Default_Model_Calendar) and view (in Default_View_Helper_CalendarTable) are completely separated, giving you the freedom to use any other model with the view helper, or simply not using any view helper with your model!

Related

Can not get my function to accept the PHP mysqli query array

I try to make a table where some cells shall have info according to an data base. If I do like this it works:
$date->modify('-1 day');
for ($x = 1; $x <=7; $x++) {
$date->modify('+1 day');
$b = true;
echo "<tr>", PHP_EOL;
echo "<td id='dag".$x."0' class='dag'>v".$date->format('W-D j/n')."</td>", PHP_EOL;
//*********** to function
foreach($t_tider as $field){
if ($field['datum'] == $date->format('Y-m-d') && $field['slot'] == 1){
echo "<td id='dag".$x."1'><div class='bokad'>".$field['lgh_nr']."-".$field['last_name']."</div></td>", PHP_EOL;
$b = false;
}
}
//***********
if($b) {
echo "<td id='dag".$x."1'>Ledig</td>", PHP_EOL;
}
// and so on, 7 rows and 5 columns and a header row
// but if I try to make a function of it it don’t recognize the array, only the first post are there.
function checkBokn($st, $tid, $d, $i){
foreach($st as $field){
if ($d->format('Y-m-d') == $field['datum'] && $field['slot'] == $tid){
echo "<td id='dag".$i.$tid."'><div class='bokad'>".$field['lgh_nr']."-".$field['last_name']."</div></td>", PHP_EOL;
return $bol = false;
}
// solved
/* else {
return $bol = true;
} */
}
return $bol = true; //moved
}
$b = checkBokn($t_tider, 2, $date, $x);
the $t_tider are an mysqli query.
BTW
Are there some way to add and subtract dates in strftime(), like on $date->modify('+1 day'); or make $date show days in another language than English?
Well I "solved" it, the else return breaks the loop, feeling stupid. Had to be after the loop.

Ajax request from overridden component of joomla template

I'm new guy in joomla and i was searching for the answer a lot of time, but didn't get the result. I have my template in joomla 3.4.5 and i have overridden component com_content and category inside it. I made my file blog.php where i output my calendar. The problem is to send ajax changing month by clickng proper button. There is an error, when i'm trying to send ajax. Seems like joomla bans direct request. I read many articles, like how to use ajax in modules and components, but there is no advice how to use it in overriden component. Please give me detailed answer for my problem.
JHtml::_('jquery.framework');
$document = JFactory::getDocument();
$document->addScript('/space/media/media/js/mainscript.js');
i used that code to include my scriptfile in blog.php
function getAjaxData()
{
echo 'login: ' .$_REQUEST['month'] . '; password: ' . $_REQUEST['year'];
exit;
}
created method to handle my ajax request in blog.php
var j = jQuery.noConflict()
j(document).ready(function(){
j('#next').click(function(){
var month = j(this).data('month');
var year = j(this).data('year');
if(month == 12){
year +=1;
month = 1;
}
else{
month++;
}
j.post("/space/templates/forte/")
j.ajax({
url: "index.php?option=com_content&view=category&task=getAjaxData&format=raw",
type: "POST",
data: {
month: month,
year: year
},
success: function(data){
j('#calendar_wrap').html(data);
}
});
console.log('month: '+month+' year: '+year);
})
j('#prev').click(function(){
var month = j(this).data('month');
var year = j(this).data('year');
if(month == 1){
year -=1;
month = 12;
}
else{
month--;
}
j.ajax({
url: "index.php?option=com_content&view=category&task=getAjaxData&format=raw",
type: "POST",
data: {
month: month,
year: year
},
success: function(data){
j('#calendar_wrap').html(data);
}
});
console.log('month: '+month+' year: '+year);
})
});
mainscript.js, included in blog.php
Synchronous XMLHttpRequest on the main thread is deprecated because of
its detrimental effects to the end user's experience. For more help,
check http://xhr.spec.whatwg.org/
here is the error outputted to browser console
I solve problem with that error by putting that method:
public function getAjaxData()
{
}
In file: /site/components/com_content/controller.php
but, i have one more problem now.
In that method my calendar outputs again, but now we have new values, send by ajax. The code below:
public function getAjaxData()
{
JHtml::_('jquery.framework');
$document = JFactory::getDocument();
$document->addScript('/space/media/media/js/mainscript.js');
function days_in_month($month, $year)
{
// calculate number of days in a month
return $month == 2 ? ($year % 4 ? 28 : ($year % 100 ? 29 : ($year % 400 ? 28 : 29))) : (($month - 1) % 7 % 2 ? 30 : 31);
}
// get number of days in needed month
$currentYear = date('Y');
$currentMonth = date('n');
if(isset($_REQUEST['year']))
$currentYear = $_REQUEST['year'];
if(isset($_REQUEST['month']))
$currentMonth = $_REQUEST['month'];
$rusmonth = array('Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь');
$dayofmonth = days_in_month($currentMonth, $currentYear);
// count for days in month
$day_count = 1;
// 1. first week
$num = 0;
for($i = 0; $i < 7; $i++)
{
// get day of week
$dayofweek = date('w',
mktime(0, 0, 0, $currentMonth, $day_count, $currentYear));
// format our values to 1-monday, 6-saturday
$dayofweek = $dayofweek - 1;
if($dayofweek == -1) $dayofweek = 6;
if($dayofweek == $i)
{
// if numbers of week are equal,
// put values into array $week
$week[$num][$i] = $day_count;
$day_count++;
}
else
{
$week[$num][$i] = "";
}
}
// 2. other weeks of month
while(true)
{
$num++;
for($i = 0; $i < 7; $i++)
{
$week[$num][$i] = $day_count;
$day_count++;
// if we got the end of the month exit from loop
if($day_count > $dayofmonth) break;
}
if($day_count > $dayofmonth) break;
}
// 3. output array $week
echo '<div> <span id="prev" data-month="'.$currentMonth.'" data-year="'.$currentYear.'"><</span> '.$rusmonth[$currentMonth-1].' <span id="next" data-month="'.$currentMonth.'" data-year="'.$currentYear.'">></span> </div>';
echo '<div id="calendar_wrap">';
echo '<table border=1>';
echo '<tr>
<th>ПН</th>
<th>ВТ</th>
<th>СР</th>
<th>ЧТ</th>
<th>ПТ</th>
<th>СБ</th>
<th>ВС</th>
</tr>';
for($i = 0; $i < count($week); $i++)
{
echo "<tr>";
for($j = 0; $j < 7; $j++)
{
if(!empty($week[$i][$j]))
{
if($j == 5 || $j == 6)
echo "<td><font color=red>".$week[$i][$j]."</font></td>";
else echo "<td>".$week[$i][$j]."</td>";
}
else echo "<td> </td>";
}
echo "</tr>";
}
echo "</table>";
echo '</div>';
exit;
}
in that method i can't add my script again to get new month.
So there are two ways for me as I see:
1. make my method that way, so he become something like a bridge between blog.php and ajax. There will be no outputs.
Find a way, how could i add script to controller and make double code.
The problem is, that i have no idea, how realize both of it in Joomla...
Of course i prefer 1st variant.

How to append a variable to a object in php

I have this, that doesnt work obviously.
$start = $hours->start{$day};
I need to be able the change the $day dynamically. $day can be any day of the week
//For example
$start = $hours->startSunday;
Let me try to be more clear. The following objects contain a certain time
// will echo something like 8:00am
echo $hours->startSunday;
//will echo something like 7:00am
echo $hours->startMonday;
I need to be able to change the day part dynamically with a variable, since it can be any day of the week.
//so something like
echo $hours->start.$day;
but that doesnt work
First. You could edit syntax with
$hours = new stdClass();
$day = 'Sunday';
$hours->{'start'.$day} = 10;
$start = $hours->{'start'.$day};
var_dump($start);
Secnod. Better ot use getter and setter methods.
class Hours
{
private $hours = array();
public function getStart($day)
{
return $this->hours[$day];
}
public function setStart($day, $value)
{
$this->hours[$day] = $value;
}
}
$hours = new Hours();
$day = 'Sunday';
$hours->setStart($day, 10);
$start = $hours->getStart($day);
var_dump($start);
You can use magic method, __get() and __set()
class Hours {
private $data = array();
public function __get($day) {
return $this->data[$day];
}
public function __set($day, $val) {
$this->data[$day] = $val;
}
}
$h = new Hours();
echo $hours->startMonday;

generating resources for each level of building

Is it possible to change this code into function without using a loop?
$start = 80;
for ($i = 1; $i <= 10; $i++) {
$start = $start * 1.5;
echo "level ".$i.": ".$start."<br>";
}
function generate($start, $level){
// some code
return $start;
}
For level 1 you have:
$start = $start * 1.5;
For level 2 $start is result from level 1, so:
$start = ($start * 1.5) * 1.5;
This same as
$start = $start * 1.5 * 1.5;
And can be simplified to
$start = $start * pow(1.5, $level);
In the end your function should look like:
function generate($start, $level){
return $start * pow(1.5, $level);
}
if you want to get the same result(include the level print to screen) you can use this code:
function generate2($start, $from,$to){
if($from==$to+1)
return 1.5;
$tmp=$start*1.5;
echo "level ". ($from).": ".$tmp."<br>";
return 1.5*generate2($tmp,$from+1,$to);
}
Or this:
<?php
define ("MAX_LEVEL",10) ;
function generate($start, $level)
{
if($limit==0)
return 1.5;
$tmp=$start*1.5;
echo "level ". (MAX_LEVEL-$level+1).": ".$tmp."<br>";
return 1.5*generate($tmp,$level-1);
}
Here some check code:
$start = 80;//<=================your code
for ($i = 1; $i <= 10; $i++) {
$start = $start * 1.5;
echo "level ".$i.": ".$start."<br>";
}
echo"---------------------------- <br>";
generate(80,10);//<====================my code
echo"---------------------------- <br>";
generate2(80,1,10);
?>
if you not need the prints you can use very simple function:
function generate($start, $level){
return $start * pow(1.5, $level);
}
Here you go, a solution without "visible" loop:
generate(80,10);
function generate($start, $level){
$i=1; // Just a var
$array = array_fill(0, $level, $start); // create an array with $level elements, with value $start
array_map(function($v)use(&$i){ // Loop through the array and use $i
echo "Level $i: ".(array_product(array($v, pow(1.5, $i++))))."<br>"; // Some basic math and output
}, $array);
}
Online demo
Note that you'll need PHP 5.3+ since this function is using an anonymous function
Or, if you need just to output $start:
function generate($start, $limit)
{
$start = $start * 1.5;
echo $start."<br>";
if($limit>1)
return(generate($start,$limit-1));
}
generate(80,10);
My question - how to properly echo $level, without third parameter (0, in this case which should be incremented, no decremented:))? :)
EDIT: I would like to know better solution which will do the same, with two args:
function generate2($start, $limit,$base)
{
$start = $start * 1.5;
echo "level ".$base.": ".$start."<br>";
if($base<$limit)
return(generate2($start,$limit,$base+1));
}
generate2(80,10,1);
And final edit:
function generate($start, $limit,$i=0)
{
$i++;
$start = $start * 1.5;
echo "level ".$i.": ".$start."<br>";
if($limit>1)
{
return(generate($start,$limit-1,$i));
}
}
generate(80,10);
as answer to my self. :) Please test it (before down votes:)), and let me know about issues... Oh, i see - OP wants just 1 result, LOL...
Question wasn't clear to me (and not just to me, it seems) :)

Change variable inside function foreach loop

I've a problem that i can't solve. I think it's an easy fix, but after 3 hours of searching and trail-error. I've decided to ask the question over here:
This is my time function for a schedule application.
date_default_timezone_set('Europe/Amsterdam');
$current_time = time();
$unixtime = $current_time;
$time = date("Gi",$unixtime);
global $time;
function time_left($time, $active_class, $maxtime, $mintime){
if($time < $maxtime and $time > $mintime){
global $active_class;
$active_class = 'active';
echo 'succes!';
}
}
Here is my foreach loop, i loop through an array
foreach($rows as $row){
switch($hours){
case 1:
$t = '8:45 - 9:15';
$mintime = 845;
$maxtime = 914;
time_left($time, $maxtime, $mintime);
break;
case 2:
$t = '8:45 - 9:15';
$mintime = 845;
$maxtime = 914;
time_left($time, $maxtime, $mintime);
break;
/* etc.. etc.. etc... */
}
echo "<li class='" . $active_class ."'>";
echo "<div class='right'></div>";
echo "<div class='hour'>", $times, "</div><span class='divider-time'>|</span>";
$hours++;
$i = 0;
foreach($row[$day] as $r[1]){
$i++;
if ($i == 1) {
$class = 'vk';
} elseif ($i == 2) {
$class = 'lok';
} elseif ($i == 3) {
$class = 'doc';
}
echo "<span class='" . $class . "'>", $r[1], "</span>";
}
echo "</li>";
$class++;
}
I get the 'succes!' echo on the right location. But the active class is not working properly. The idea behind it is that the active class is only shown on one row. Now it searches for a match and everything behind it also gets the active class.
Thanks in advanced.
You should restart the $active_class variable in every iteration.
Otherwise, once it is set to active it won't change its value again.
foreach($rows as $row){
$active_class = '';
//YOUR CODE HERE
....
}

Categories