Ok I just started kostache and I would like to display the results i got from the database using orm in kohana 3.3. I know how to display them using foreach statement but when using kostache it's way different. So here's my code.
APPATH/classes/controller/album.php
class Controller_Album extends Controller
{
public function action_index()
{
$view = Kostache_Layout::factory();
$this->response->body($view->render(new View_Pages_Album_List));
}
}
APPATH/classes/view/pages/album/list.php
class View_Pages_Album_List {
public $title = 'List of Music';
public function album_list()
{
$albums = ORM::factory('Album_Information')->find_all();
return $albums;
}
}
APPATH/templates/pages/album/list.mustache
{{album_list}}
How would i display the resulst?. How would you do this in kostache?
Thanks and more power.
Well Nevermind I got it working..
public function album_list()
{
$albums = ORM::factory('Album_Information')->find_all();
$album_info = array();
foreach ($albums as $a)
{
$album = array('album' => array('artist' => $a->Artist, 'album_name' => $a->Album_Name,));
$album_info[] = $album;
}
return $album_info;
}
Related
I am trying to make my best OOP code to parse objects with data from database so I created a hook that call a class AppAutoLoadObjects from hooks folder.
config/hooks.php
$hook['pre_system'][] = array(
'class' => 'AppAutoLoadObjects',
'function' => 'initialize',
'filename' => 'AppAutoLoadObjects.php',
'filepath' => 'hooks'
);
hooks/AppAutoLoadObjects.php
class AppAutoLoadObjects
{
public function initialize()
{
spl_autoload_register(array($this,'autoloadCoreObjects'));
}
public function autoloadCoreObjects($class)
{
$path = array(
'objects/',
);
foreach($path as $dir) {
if (file_exists(APPPATH.$dir.$class."_Object".'.php'))
require_once(APPPATH.$dir.$class."_Object".'.php');
}
}
}
As you see in the code I have a objects folder where I require the object parser.
So if I have models/Products_model.php, the autoloadCoreObjects automatically loads objects/Products_Object.php .
Then in my Products_model.php I use on each function:
public function select_by_limit($start, $limit, $resolution) {
..........................................
$query = $this->db->get_compiled_select();
$result = $this->db->query($query);
return $result->custom_result_object('Products_Object');
}
So my object with items from database are parsed in Products_Object.php
class Proprietati_Object
{
private $_resolution;
public function __construct($resolution = 270){
$this->_resolution = $resolution;
$this->_ci = get_instance();
}
//here is where I check if any image in database and if not give a default
public function image(){
if($this->image_name):
return base_url('assets/uploads/'.$this->id_proprietate.'/'.$this->image_resolution());
else:
return base_url('assets/images/no-product-image-available.png');
endif;
}
//here is where I load a small part of view as string because I must show in view different html code for each product_type
public function get_block_caracteristics(){
if($this->product_type == 'apartament')
return $this->_ci->load->view('blocks/apartament', array('product' => $this), TRUE);
elseif($this->product_type == 'land')
return $this->_ci->load->view('blocks/land', array('product' => $this), TRUE);
}
//here is where I set the image resolution and depends on each page where I show the products. E.g. 100, 200, 500
private function image_resolution() {
$image = explode('.', $this->image_name);
return $image[0].'_'.$this->_resolution.'.'.$image[1];
}
}
With this approach I have my controller clean and I only use:
$products = $this->products->select_by_limit(0, 10);
$data['products'] = $products;
then in view:
<?php foreach($products as $product): ?>
<?= $product->image() ?>
<?= $product->get_block_caracteristics() ?>
<?php endforeach; ?>
My question is how can I pass the $resolution variable from the model to the Products_Object constructor? Or maybe my approach is not a good one?
I now this is a very detailed question but I am dealing with this from long time ago, and my purpose is to start coding with clean controllers and models. The framework I use is CodeIgniter.
your model
public function select_by_limit($start, $limit, $resolution)
{
$query = $this->db->get_compiled_select();
$result = $this->db->query($query);
$arrData = array();
foreach($result->result("Proprietati_Object") AS $objProduct)
{
$objProduct->setResolution($resolution);
$arrData[] = $objProduct;
}
return $arrData;
}
and in your Proprietati_Object add a function called setResolution
public function setResolution($resolution)
{
$this->_resolution = $resolution;
}
and thats it
Inside my processor class I have a statement that grabs all the projects from a db table and formats them to be displayed. This method does not work and halts at the getCollection call.
class GlobalLinkSettingsProcessor extends modObjectGetListProcessor{
public function initialize() {
return parent::initialize();
}
public function process() {
$result = $this->modx->getCollection('ManagerProjects');
$project_names = array();
foreach ($result as $row) {
$projects = unserialize($row->get('manager_projects'));
foreach($projects as $short_code => $project) {
$project_names[] = array('project_name' => $project, 'project_short_code' => $short_code);
}
}
return '{"total":' . count($project_names) . ',"results":' . $this->modx->toJSON($project_names) . ',"success":true}';
}
...
}
This code that uses plain SQL does work:
class GlobalLinkSettingsProcessor extends modObjectGetListProcessor{
public function initialize() {
return parent::initialize();
}
public function process() {
$leadersql = "SELECT * FROM `modx_manager_projects`";
$query = $this->modx->query($leadersql);
$project_names = array();
while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
$projects = unserialize($row['manager_projects']);
foreach($projects as $short_code => $project) {
$project_names[] = array('project_name' => $project, 'project_short_code' => $short_code);
}
};
return '{"total":' . count($project_names) . ',"results":' . $this->modx->toJSON($project_names) . ',"success":true}';
}
...
}
I use similar method to the first which saves ManagerProjects and works fine, so I don't think it has to do with the model declaration. I could easily just use the second method above since it seems to work, but I want to use the best method.
What is wrong with the first method?
Is the first method the proper way to implement SQL in the Modx processor? Or is there a better way?
We can do this task easier a little bit.
#Vasis is right but we can use base prepareRow method instead of reloading iterate method:
<?php
class GlobalLinkSettingsProcessor extends modObjectGetListProcessor{
public $classKey = 'ManagerProjects';
protected $projects = array();
public function prepareRow(xPDOObject $object) {
$_projects = unserialize($object->get('manager_projects'));
foreach($_projects as $short_code => $project) {
$this->projects[] = array('project_name' => $project, 'project_short_code' => $short_code);
}
return parent::prepareRow($object);
}
public function outputArray(array $array,$count = false) {
$count = count($this->projects);
return parent::outputArray($this->projects,$count);
}
}
return 'GlobalLinkSettingsProcessor';
There we can see one of modx ‘features’. In modObjectGetListProcessor process method we can see this:
public function process() {
$beforeQuery = $this->beforeQuery();
if ($beforeQuery !== true) {
return $this->failure($beforeQuery);
}
$data = $this->getData();
$list = $this->iterate($data);
return $this->outputArray($list,$data['total']);
}
getData method returns a list of objects and it goes to iterate method (where we can check if the object is accessible and change the list of these objects on demand). If you don't have access to some of objects we'll get changed list. And it goes to outputArray method but second parameter is still old for it. So you should count them again.
This is solution is quite well but you tried to get data which is stored in object's field. So afterIteration method will be unusable for further extension in my version of processor. But who cares? :)
P.S.: About your first version of processor. modObjectGetList processor is ready for getting collection. So you have not to use getcollection method. Just add proper classKey property to it.
Another way is in modProcessor extension. It gives to you a base structure. But you can make your own kind of stuff.
Because you do it wrong! Just see this. The right way to do it, is something like this:
<?php
class GlobalLinkSettingsProcessor extends modObjectGetListProcessor{
public $classKey = 'ManagerProjects';
public function iterate(array $data) {
$list = array();
$list = $this->beforeIteration($list);
$this->currentIndex = 0;
/** #var xPDOObject|modAccessibleObject $object */
foreach ($data['results'] as $object) {
if ($this->checkListPermission && $object instanceof modAccessibleObject && !$object->checkPolicy('list')) continue;
$projects = unserialize($object->get('manager_projects'));
foreach($projects as $short_code => $project) {
$objectArray = array('project_name' => $project, 'project_short_code' => $short_code);
if (!empty($objectArray) && is_array($objectArray)) {
$list[] = $objectArray;
$this->currentIndex++;
}
}
}
$list = $this->afterIteration($list);
return $list;
}
}
I using zf2's tableGateway and I'm unsure of the design it leads to.
Here is the canonical example of how to use zf2's tableGateway to do an insert (this from the docs):
public function saveAlbum(Album $album)
{
$data = array(
'artist' => $album->artist,
'title' => $album->title,
);
$id = (int)$album->id;
if ($id == 0) {
$this->tableGateway->insert($data);
} else {
if ($this->getAlbum($id)) {
$this->tableGateway->update($data, array('id' => $id));
} else {
throw new \Exception('Form id does not exist');
}
}
}
But defining the $data array seems redundant because I already have an Album class that looks like this:
class Album
{
public $id;
public $artist;
public $title;
public function exchangeArray($data)
{
$this->id = (isset($data['id'])) ? $data['id'] : null;
$this->artist = (isset($data['artist'])) ? $data['artist'] : null;
$this->title = (isset($data['title'])) ? $data['title'] : null;
}
}
In my own project I have a model with about 25 properties (a table with 25 columns). It seems redundant to have to define the class with 25 properties and than also write a $data array inside of the method of a class implementing tableGateway with an element for every one of those properites. Am I missing something?
Another way is to use RowGateway http://framework.zend.com/manual/2.3/en/modules/zend.db.row-gateway.html
Briefly, I'd extend album class from \Zend\Db\RowGateway\AbstractRowGateway class.
<?php
namespace Module\Model;
use Zend\Db\RowGateway\AbstractRowGateway;
use Zend\Db\Adapter\Adapter;
use Zend\Db\Sql\Sql;
class Album extends AbstractRowGateway
{
protected $primaryKeyColumn = array( 'id' );
protected $table = 'album';
public function __construct( Adapter $adapter )
{
$this->sql = new Sql( $adapter, $this->table );
$this->initialize();
}
}
And then you can do like this
$album->title = "Some title";
$album->save();
Or
$album->populate( $dataArray )->save();
You may want to take a look at my QuickStart 101 Tutorial.
Basically you could do:
saveAlbum(Album $albumObject)
{
$hydrator = new ClassMethods(false);
$albumArray = $hydrator->extract($albumObject);
// v-- not too sure if that one-liner works; normal if() in case it doesn't
isset($albumArray['id']) ? unset($albumArray['id']) :;
// insert into tablegateway
}
Can something like this be done? I want to pass a variable from a public function to my view.
public function index() {
$home_data['username'] = "myname";
$home_data['cool'] = $this->variable;
$this->load->view('home_view', $home_data);
}
public function a_function() {
public $variable = "cool";
}
//EDIT//
This is what I m actually trying to accomplish and I m stuck.
get_two gets two items from a table. I want to add the two items to two variables and pass them to the view.
public function get_two() {
$get_results = $this->home_model->get_two_brands();
if($get_results != false){
$html = '';
foreach($get_results as $result){
$html .= '<li>'.$result->brand.'</li>';
}
$result = array('status' => 'ok', 'content' => $html);
header('Content-type: application/json');
echo json_encode($result);
exit();
}
}//public function get_two() {
Should I create two functions like this? But I don't know how to pass the $get_results array from get_two to the below functions. I tried public $get_results = $this->model ... etc but that didn't work.
public function result_one() {
return $resultOne = $get_results[0];
}
public function result_two() {
return $resultTwo = $get_results[1];
}
I'm not sure I've got the question correctly but what you're trying to achieve is something like this?
public function index() {
$home_data['username'] = "myname";
$home_data['cool'] = $this->a_function();
$this->load->view('home_view', $home_data);
}
public function a_function() {
return $variable = "cool";
}
/** AFTER EDIT **/
Things get complicated (possibly because of my english comprehension).
you said
get_two gets two items from a table. I want to add the two items to two variables and pass them to the view.
So from the function get_two() you need to get and use the result in this way?
public function index() {
$home_data['username'] = "myname";
$home_data['cool'] = $this->get_two(); // <- here?
$this->load->view('home_view', $home_data);
}
So you can try with:
public function get_two() {
$get_results = $this->home_model->get_two_brands();
if($get_results != false){
return $get_results;
}
}
and then
public function index() {
$home_data['username'] = "myname";
$home_data['cool'] = $this->get_two();
$this->load->view('home_view', $home_data);
}
and inside you home_view :
<?php
foreach($home_data['cool'] as $result){
echo '<li>'.$result->brand.'</li>';
}
?>
/** AFTER NEW QUESTION **/
I need the ids of the two choices as two distinct variables
So change the index function this way:
public function index() {
$home_data['username'] = "myname";
$home_data['cool'] = $this->get_two(); // <- maybe you don't need this anymore
list($result1, $result2) = $this->get_two();
$home_data['resultId1'] = $result1->id;
$home_data['resultId2'] = $result2->id;
$this->load->view('home_view', $home_data);
}
Now you're able to use $home_data['resultId1'] and $home_data['resultId1'] inside your view.
You can also define the variable in the constructor, this is one way .
CODE:
public function __construct(){
$this->variable = "cool";
}
public function index() {
$home_data['username'] = "myname";
$home_data['cool'] = $this->variable;
$this->load->view('home_view', $home_data);
}
I don't know the codeigniter framework so this is why I asked for a part of your view but it looks pretty simple as I check in the doc. And the doc's are not bad there.
Check for Adding Dynamic Data to the View
public_function() should return something, for ex:
function public_function() {
return 'groovy';
}
Then call it in the controller:
public function index() {
$home_data['username'] = "myname";
$home_data['cool'] = $this->public_function();
$this->load->view('home_view', $home_data);
}
Then add to the view somewhere
<?php echo $home_data['cool'];?>
I assume it's wrapped in some class. So if you cannot return the value you need (for ex. function already returns something else) then do something like this:
class Someclass {
public $some_class_variable;
function public_function() {
$this->some_class_variable = 'groovy';
}
function index() {
$home_data['cool'] = $this->some_class_variable;
}
}
I have found this function in the documentation from Zend, more specific in the Create model and Database Table section ( http://framework.zend.com/manual/1.12/en/learning.quickstart.create-model.html ).
This is in the Application_Model_GuestbookMapper:
public function save(Application_Model_Guestbook $guestbook)
{
$data = array(
'email' => $guestbook->getEmail(),
'comment' => $guestbook->getComment(),
'created' => date('Y-m-d H:i:s'),
);
if (null === ($id = $guestbook->getId())) {
unset($data['id']);
$this->getDbTable()->insert($data);
} else {
$this->getDbTable()->update($data, array('id = ?' => $id));
}
}
and now i would like to integrate this into my controller, but i have no idea how?
I created an instance of the mapper and tried to pass the info from my decoded json string to it, but I still get errors...:
public function indexAction()
{
$mapper = new Application_Model_GuestbookMapper();
$db = Zend_Db_Table_Abstract::getDefaultAdapter();
$json = file_get_contents('http://data.appsforghent.be/poi/apotheken.json');
$data = Zend_Json::decode($json);
foreach($data['apotheken'] as $row)
{
$mapper->save();
}
}
I know i have to pass the $data to the save() function but I have no idea how... The model won't fit the json-url, I just wanted to show how I retrieve and decode the json.
Can anybody help me?
What you need to pass in to the $mapper->save(); is an instance of Application_Model_Guestbook. So hopefully you have a class Application_Model_Guestbook in which you define the possibility to set a data array as its attributes, for example like this:
class Application_Model_Guestbook {
private $email,$comment,$created;
public function __construct($data) {
$this->email = $data['email'];
// etc add other variables
}
public function getEmail() {
return $this->email;
}
}
Then to call that, use:
foreach($data['apotheken'] as $row)
{
$guestbook = new Application_Model_Guestbook($row);
$mapper->save($guestbook);
}
I have not tested this specifically, but it should give you an idea of how to achieve what you want to do.