Kohana: trying to dynamically change content (not the whole page) - variables

I am struggling to get my head around this since too many hours and I need some help.:)
I have a website build on Kohana and want to dynamically change the content of some text when the user click one button or and another. Not sure if I am doing it the right way but this what I did so far (ho by the way I am new to this framework).
Controller:
class Controller_Homepage extends Controller_General {
public $template = "template/widepage";
public $textbuyer = array (
'text1' => "homepage.buyer.bigtext1", //transfering language variable.
'text2' => "homepage.buyer.bigtext2",
//with more ...
);
public $textseller = array (
'text1' => "homepage.seller.bigtext1",
'text2' => "homepage.seller.bigtext2",
'text3' => "homepage.seller.bigtext3",
//with more ...
);
public $thetext = array ("textbuyer"); //the defaul array is textbuyer
public function action_index() {
$this->content = View::factory("homepage")
->bind('pagetext', $thetext );
if ($this->request->method() === Request::POST) {
$post= $this->request->post();
if (isset($post['buyer'])){
$thetext = $textbuyer;//gives rrorException [ Notice ]: Undefined variable: textbuyer
// arr::overwrite($thetext, $textbuyer);
}else if(isset($post['seller'])){
$thetext = $textseller;
}
}
}
Section of my view to show how I use the variable in the view:
<div class="container_content">
<div>
<p id='sline'><?php echo $pagetext['text1']; ?></p>
</div>
<div>
Can't get the content of my array to the view and when I click on one of the two buttons this code gives me the following error: ErrorException [ Notice ]: Undefined variable: textbuyer. What I am doing wrong ? Why I get the error I mentionned ?
Thank you!

When you define the variables like this
public $textbuyer = ...
public $textseller = ...
public $thetext = ...
They are attributes of your class. And since they are, you need to call them via
$this->textbuyer
$this->textseller
$this->thetext
Just as you call methods inside the same class with $this->methodName() instead of methodName().
class Foo {
public $bar = "hello ";
public function foo() {
$bar = "world";
print $this->bar.$bar; // hello world
}
}
This would work just fine and you get the error because you never define $textbuyer (because you want to call $this->textbuyer).

Related

Referencing a global variable in forloop from Apache Velocity

I am having trouble with having a formatter within a forloop in Apache Velocity.
#set( $array = ["10000", "3000", "13.456", "1111.13"] )
<ul>
#foreach( $a in $array)
<li>$formatter.print($a)</li>
#end
</ul>
This would be evaluated and print the original expression as a string 4 times
$formatter.print($a)
$formatter.print($a)
$formatter.print($a)
$formatter.print($a)
instead of
10,000.00
3,000.00
13.456
1,111.13
However it seems to work fine with the formatter outside of the scope from the forloop
<p>$formatter.print(123456)</p>
This would work as usual
Can anyone helps me figuring out how to reference a property (in this case $formatter) within a for loop ?
This can happen when one of the following condition is true:
1) The model passed to the velocity does not have the variable "formatter"
2) The method print is returning null or it does not exist
3) The method print accepts a parameter of the wrong type. Try to pass Object...
The following code works for me (notice that I am using an array of double and not any more an array of string):
package test;
import java.io.StringWriter;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
public class VelocityHelloWorld
{
public static void main( String[] args )
throws Exception
{
VelocityEngine ve = new VelocityEngine();
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
ve.init();
VelocityContext context = new VelocityContext();
context.put("formatter", new Formatter());
Template t = ve.getTemplate( "helloworld.vm" );
StringWriter writer = new StringWriter();
t.merge( context, writer );
System.out.println(writer.toString());
}
}
Velocity:
#set( $array = [10.00 , 20.00, 13.456, 1111.13] )
<ul>
#foreach( $a in $array)
<li>$formatter.print($a)</li>
#end
</ul>
Formatter:
package test;
public class Formatter {
public String print (Object d) {
String s = d.getClass().getName() + ": " + d.toString();
return s;
}
}
The template shows the same behaviour like yours if I substitute in
print (Double d)
Double with Float.
Long story short... I think that you probably need to check the parameter passed to your method.
Of course I think you should use Double and create the array as a list of double and not as a list of strings.
Try ${myref.doIt($var)} syntax to reference context variable. This ensures Velocity does not parse context names incorrectly within strings.

Test contents of return array in PHPSpec

Say I have this method of a RuleFactory:
public function makeFromArray($rules)
{
$array = [];
foreach ($rules as $rule) {
$array[] = new Rule($rule[0], $rule[1]);
}
return $array;
}
I want to test that the return array contains Rule elements. Here is my test:
function it_should_create_multiple_rules_at_once()
{
$rules = [
['required', 'Please provide your first name'],
['alpha', 'Please provide a valid first name']
];
$this->makeFromArray($rules)->shouldHaveCount(2);
$this->makeFromArray($rules)[0]->shouldBeInstanceOf('Rule');
$this->makeFromArray($rules)[1]->shouldBeInstanceOf('Rule');
}
But this does not work, it throws an error in PHPSpec.
The strange thing is that I can do this just fine on other methods that return arrays, but for some reason I cannot do that here.
The error I get is this:
! it should create multiple rules at once
method [array:2] not found
How do I test the contents of this return array, WITHOUT creating my own inline matcher?
Your method accepts a single rule, not all of them. The spec should be:
$this->makeFromArray($rules)->shouldHaveCount(2);
$this->makeFromArray($rules[0])[0]->shouldBeAnInstanceOf('Rule');
$this->makeFromArray($rules[1])[1]->shouldBeAnInstanceOf('Rule');
Or, to avoid multiple calls:
$rules = $this->makeFromArray($rules);
$rules->shouldHaveCount(2);
$rules[0]->shouldBeAnInstanceOf('Rule');
$rules[1]->shouldBeAnInstanceOf('Rule');
Still, the most readable version would be the one leveraging a custom matcher:
$rules->shouldHaveCount(2);
$rules->shouldContainOnlyInstancesOf('Rule');

Laravel 4 - Call to a member function actividads() on a non-object (pivote table)

I'm trying to save in my DB the relation between two tables actividads and fichas (through a pivot table: actividad-ficha. And I'm having this message:
Symfony \ Component \ Debug \ Exception \ FatalErrorException (E_ERROR)
Call to a member function actividads() on a non-object
I pass through my Route two variables (ids):
Route::get('ficha/{id_ficha}/{id_actividad}', array('uses' => 'FichaController#enFicha'));
And then, in my 'FichaController':
public function enFicha($id_ficha, $id_actividad)
{
$ficha = Ficha::find($id_ficha);
// $actividad_id = Actividad::find($id_actividad); (doesnt work)
$actividad_id = $id_actividad;
$ficha->actividads()->sync($actividad_id, false);
return Redirect::route('actividads.index');
}
Here my models:
class Actividad extends Eloquent {
protected $guarded = array();
public function fichas()
{
return $this->belongsToMany('Ficha', 'actividad_ficha')->withTimestamps(); //
}
class Ficha extends Eloquent {
protected $guarded = array();
public function actividads()
{
return $this->belongsToMany('Actividad', 'actividad_ficha')->withTimestamps();
}
After change what #decco and #Ben suggested me, I have the next error message:
Argument 1 passed to Illuminate\Database\Eloquent\Relations\BelongsToMany::formatSyncList() must be of the type array, string given, called in /Applications/XAMPP/xamppfiles/htdocs/webs/lara4/edu1/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php on line 578 and defined
I don't know what is wrong with that... Any idea??
Thank you very much!!
$ficha = $id_ficha;
$ficha->actividads()->sync($actividad_id);
There's your problem. $ficha is a String, not an object.
Change the first line with $ficha = Ficha::find($id_ficha) which should return the Ficha object with ID $ficha_id or null.
Also you need to change the second line with $ficha->actividads()->attach($actividad_id).

Play framework select input validation

I am using Play 2.1
I made a select drop down box using the helper field constructor.
The drop down box have 3 fields, default:"choose a gender", Male, and Female.
How do I ensure that the user choose one of male or female, and not the default value? (A required drop down field)
I am using Play!Framework 2.1.0, below is a simple solution for your problem:
The model should be like this: (Below is simple model for your problem)
package models;
import play.data.validation.Constraints;
public class Gender {
// This field must have a value (not null or not an empty string)
#Constraints.Required
public String gender;
}
The controller should be like this:
/** Render form with select input **/
public static Result selectInput() {
Form<Gender> genderForm = Form.form(Gender.class);
return ok(views.html.validselect.render(genderForm));
}
/** Handle form submit **/
public static Result validateSelectInput() {
Form<Gender> genderForm = Form.form(Gender.class).bindFromRequest();
if (genderForm.hasErrors()) { // check validity
return ok("Gender must be filled!"); // can be bad request or error, etc.
} else {
return ok("Input is valid"); // success validating input
}
}
The template/view should be like this:
#(genderForm: Form[models.Gender])
#import views.html.helper._
#main(title = "Validate Select") {
#form(action = routes.Application.validateSelectInput()) {
#********** The default value for select input should be "" as a value *********#
#select(
field = genderForm("gender"),
options = options("" -> "Select Gender", "M" -> "Male", "F" -> "Female")
)
<input type="submit" value="Post">
}
}
See also this post as reference : Use of option helper in Play Framework 2.0 templates

set const in controller and call in view as dropdown list in yii

I have three const in controller:
const TEST1 = 1;
const TEST2 = 2;
const TEST3 = 3;
How I can call these values in view as a dropDown?
If you will get messy with all constants you have in diferent models, you can use code snippet I wrote to manage them. Please see Managing constants easily (yii wiki article)
I will copy just function and one example, but for full wiki and details please go visit link above.
Put this method in parent class or your model class directly:
class ActiveRecord extends CActiveRecord {
const TEST_1 = 1;
const TEST_2 = 2;
const TEST_3 = 3;
/*
Get class constants by token.
If you set constants with same prefix, like:
TEST_1
TEST_2
TEST_3
, you can get it by calling
Class::getConstants('TEST_');
*/
public static function getConstants($token,$objectClass) {
$tokenLen = strlen($token);
$reflection = new ReflectionClass($objectClass); //php built-in
$allConstants = $reflection->getConstants(); //constants as array
$tokenConstants = array();
foreach($allConstants as $name => $val) {
if ( substr($name,0,$tokenLen) != $token ) continue;
$tokenConstants[ $val ] = $val;
}
return $tokenConstants;
}
}
And after that you can use this method to get specific constants (from one group) in array:
self::getConstants('TEST_',__CLASS__); //inside same class
ActiveRecord::getConstants('TEST_','ActiveRecord'); //outside, somewhere else in view or controller
For dropdown it would be looking as (if MyModel have parent ActiveRecord)
echo CHtml::dropDownList('name','selected',
MyModel::getConstants('TEST_','MyModel'),
array(// for htmlOptions
)
);
Now you can forget to edit all places in code if you adding new constant. It will automaticaly added to all your dropdowns or whatever.
Simple, just use:
$this::TEST1;
In dropdownList:
echo CHtml::dropDownList('name','selected',
array($this::TEST1=>'Test1',$this::TEST2=>'Test2',$this::TEST3=>'Test3'),
array(// for htmlOptions
)
);