I am trying to get category related video blogs by below code but i get nothing in var_dump? I want to get category related videos:
$category = VideoBlogCategoryModel::findFirst(1); // This returns category successfully and there are many video blogs having this category linked
var_dump($category->getVideoBlogs());exit;
VideoBlogModel.php
public function initialize(){
// Run base initialize code
parent::initialize();
// Configure Relation with VideoBlogCategoryModel
$this->belongsTo('category_id', VideoBlogCategoryModel::class, 'id', array(
'alias' => 'videoCategory',
'foreignKey' => true
));
}
public function getVideoCategory(){
return $this->videoCategory;
}
public function setVideoCategory($videoCategory){
$this->videoCategory = $videoCategory;
}
VideoBlogCategoryModel.php
public function initialize(){
// Run base initialize code
parent::initialize();
// Configure relation with VideoBlogModel
$this->hasMany('id', VideoBlogModel::class, 'category_id', array(
'alias' => 'videoBlogs',
'foreignKey' => true,
'cxAction' => static::ACTION_CASCADE_DELETE
));
}
public function getVideoBlogs(){
return $this->videoBlogs;
}
public function setVideoBlogs($videoBlogs){
$this->videoBlogs = $videoBlogs;
}
Let me know if anything else is required, I will share it.
In VideoBlogCategoryModel.php change
public function getVideoBlogs() {
return $this->videoBlogs;
}
to
public function getVideoBlogs() {
return $this->getRelated('videoBlogs');
}
Then try accessing it like:
$category = VideoBlogCategoryModel::findFirst(1);
$videos = $category->getVideoBlogs();
foreach( $videos as $video ) {
// access data here
var_dump($video->anyProperty()); // e.g $video->getId()
}
can you try it
$category = VideoBlogCategoryModel::findFirst(1);
$videos = $category->getVideoBlogs();
var_dump($videos->count());
var_dump($videos->toArray());
exit;
I think use var_dump for a Phalcon Collection Object is not a good idea, you can convert it to Array and Var_dump
Hope it can help you
Or try:
$categories = VideoBlogCategoryModel::findById($id);
Is there a way to add an array of objects to a core controller of the json apiplugin
the core controller i want to modify is 'get_category_index' and it returns these objects
id
post_count
name
slug
what i want to do is an extra object, 'posts' which lists the posts that are assigned to that category
the code currently looks like this in jsonapi/controllers/core.php for that specific controller looks like that
public function get_category_index() {
global $json_api;
$args = null;
if (!empty($json_api->query->parent)) {
$args = array(
'parent' => $json_api->query->parent
);
}
$categories = $json_api->introspector->get_categories($args);
return array(
'count' => count($categories),
'categories' => $categories
);
}
and i thought something like this would do the trick
public function get_category_index() {
global $json_api;
$args = null;
if (!empty($json_api->query->parent)) {
$args = array(
'parent' => $json_api->query->parent
);
}
$categories = $json_api->introspector->get_categories($args);
return array(
'count' => count($categories),
'categories' => $categories,
'posts' => $posts,
);
}
but i'm obviously im missing something, how can i add that array of posts?
i found the category.php which looks like this
class JSON_API_Category {
var $id; // Integer
var $slug; // String
var $title; // String
var $description; // String
var $parent; // Integer
var $post_count; // Integer
var $posts; // array
function JSON_API_Category($wp_category = null) {
if ($wp_category) {
$this->import_wp_object($wp_category);
}
}
function import_wp_object($wp_category) {
$this->id = (int) $wp_category->term_id;
$this->slug = $wp_category->slug;
$this->title = $wp_category->name;
$this->description = $wp_category->description;
$this->parent = (int) $wp_category->parent;
$this->post_count = (int) $wp_category->count;
$this->posts = $wp_category->posts;
}
}
where i added the
var $posts; // array
and called it
$this->posts = $wp_category->posts;
however obviously i'm getting null on posts in my json return, whereas i need it to return the posts in that category.
I'm working on page for a SilverStripe that will allow users to sort through portfolio pieces based on the selected facets.
Here are the key points/requirements:
I have 2 facet categories they can search by: Media Type (i.e. Ads,
Posters, TV, Web) and Industry (Entertainment, Finance, Healthcare,
Sport, etc).
Users should be allowed to search multiple facets at once and also
across media type and industry at once.
In the SilverStripe admin, since content managers need to be able
to maintain the facet namesfor Media Type and Industry, I made it so
that there are 2 admin models where the names can be entered:
MediaTypeTagAdmin and IndustryTagAdmin. Here are the data object
classes for MediaTypeTag and IndustryTag that are used by the admin
models:
MediaTypeTag class
<?php
class MediaTypeTag extends DataObject {
private static $db = array(
'Name' => 'varchar(250)',
);
private static $summary_fields = array(
'Name' => 'Title',
);
private static $field_labels = array(
'Name'
);
private static $belongs_many_many = array(
'PortfolioItemPages' => 'PortfolioItemPage'
);
// tidy up the CMS by not showing these fields
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->removeByName("PortfolioItemPages");
return $fields;
}
static $default_sort = "Name ASC";
}
IndustryTag class
<?php
class IndustryTag extends DataObject {
private static $db = array(
'Name' => 'varchar(250)',
);
private static $summary_fields = array(
'Name' => 'Title',
);
private static $field_labels = array(
'Name'
);
private static $belongs_many_many = array(
'PortfolioItemPages' => 'PortfolioItemPage'
);
// tidy up the CMS by not showing these fields
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->removeByName("PortfolioItemPages");
return $fields;
}
static $default_sort = "Name ASC";
}
There needs to be a page for each Portfolio Item, so I made a PortfolioItemPage type, which has 2 tabs: one for Media Type and one for Industry Type. This is so content managers can associated whatever tags they want with each Portfolio Item by checking the appropriate boxes:
PortfolioItemPage.php file:
private static $db = array(
'Excerpt' => 'Text',
);
private static $has_one = array(
'Thumbnail' => 'Image',
'Logo' => 'Image'
);
private static $has_many = array(
'PortfolioChildItems' => 'PortfolioChildItem'
);
private static $many_many = array(
'MediaTypeTags' => 'MediaTypeTag',
'IndustryTags' => 'IndustryTag'
);
public function getCMSFields() {
$fields = parent::getCMSFields();
if ($this->ID) {
$fields->addFieldToTab('Root.Media Type Tags', CheckboxSetField::create(
'MediaTypeTags',
'Media Type Tags',
MediaTypeTag::get()->map()
));
}
if ($this->ID) {
$fields->addFieldToTab('Root.Industry Tags', CheckboxSetField::create(
'IndustryTags',
'Industry Tags',
IndustryTag::get()->map()
));
}
$gridFieldConfig = GridFieldConfig_RecordEditor::create();
$gridFieldConfig->addComponent(new GridFieldBulkImageUpload());
$gridFieldConfig->getComponentByType('GridFieldDataColumns')->setDisplayFields(array(
'EmbedURL' => 'YouTube or SoundCloud Embed Code',
'Thumb' => 'Thumb (135px x 135px)',
));
$gridfield = new GridField(
"ChildItems",
"Child Items",
$this->PortfolioChildItems(),
$gridFieldConfig
);
$fields->addFieldToTab('Root.Child Items', $gridfield);
$fields->addFieldToTab("Root.Main", new TextareaField("Excerpt"), "Content");
$fields->addFieldToTab("Root.Main", new UploadField('Thumbnail', "Thumbnail (400x x 400px)"), "Content");
$fields->addFieldToTab("Root.Main", new UploadField('Logo', "Logo"), "Content");
return $fields;
}
}
class PortfolioItemPage_Controller extends Page_Controller {
private static $allowed_actions = array (
);
public function init() {
parent::init();
}
}
What I thought might be a good approach would be to use jQuery and AJAX to send the ids of the selected facets to the server:
(function($) {
$(document).ready(function() {
var industry = $('.industry');
var media = $('.media');
var tag = $('.tag');
var selectedTags = "";
tag.each(function(e) {
$(this).bind('click', function(e) {
e.preventDefault();
$(this).addClass('selectedTag');
if(selectedTags.indexOf($(this).text()) < 0){
if($(this).hasClass('media')){
selectedTags += + $(this).attr("id") + "," +"media;";
}
else{
selectedTags += + $(this).attr("id") + "," +"industry;";
}
}
sendTag(selectedTags);
}.bind($(this)));
});
function sendTag(TagList){
$.ajax({
type: "POST",
url: "/home/getPortfolioItemsByTags/",
data: { tags: TagList },
dataType: "json"
}).done(function(response) {
var div = $('.portfolioItems');
div.empty();
for (var i=0; i<response.length; i++){
div.append(response[i].name + "<br />");
//return portfolio data here
}
})
.fail(function() {
alert("There was a problem processing the request.");
});
}
});
}(jQuery));
Then on Page.php, I loop through the ids and get the corresponding PortfolioItemPage information based on the facet ids:
public function getPortfolioItemsByTags(){
//remove the last comma from the list of tag ids
$IDs = $this->getRequest()->postVar('tags');
$IDSplit = substr($IDs, 0, -1);
//put the tag ids and their tag names (media or industry) into an array
$IDListPartial = explode(";",$IDSplit);
//This will hold the associative array of ids to types (i.e. 34 => media)
$IDListFinal = array();
array_walk($IDListPartial, function($val, $key) use(&$IDListFinal){
list($key, $value) = explode(',', $val);
$IDListFinal[$key] = $value;
});
//get Portfolio Items based on the tag ids and tag type
foreach($IDListFinal as $x => $x_value) {
if($x_value=='media'){
$tag = MediaTypeTag::get()->byId($x);
$portfolioItems = $tag->PortfolioItemPages();
}
else{
$tag = IndustryTag::get()->byId($x);
$portfolioItems = $tag->PortfolioItemPages();
}
$return = array();
foreach($portfolioItems as $portfolioItem){
$return[] = array(
'thumbnail' => $portfolioItem->Thumbnail()->Link(),
'name' => $portfolioItem->H1,
'logo' => $portfolioItem->Logo()->Link(),
'excerpt' => $portfolioItem->Excerpt,
'id' => $portfolioItem->ID
);
}
return json_encode($return);
}
}
However, this is where I am getting stuck. While I have found some decent examples of building a PHP/MySQL faceted search outside of a CMS, I am not sure what I can modify in order to make the search work inside a CMS. That, and the examples put the facets in one table in the MySQL database whereas I have 2 (As much as I want to have just one MySQL table for both the Media Type and Industry facets, I am not sure if this is a good idea since content managers want to maintain the facet names themselves).
Are there any tutorials out there that might provide further assistance, or possibly a plugin that I have not found yet? If there is a better way to set this faceted search up, by all means, please suggest ideas. This is pretty new to me.
The most efficient way to do this is to filter based on the tag/media type IDs in one query (your example is doing one database query per tag/type, then appending the results).
You should be able to do something like this:
<?php
public function getPortfolioItemsByTags(){
$tagString = $this->getRequest()->postVar('tags');
// remove the last comma from the list of tag ids
$tagString = substr($tagString, 0, -1);
//put the tag ids and their tag names (media or industry) into an array
$tags = explode(";", $tagString);
//This will hold the associative array of ids to types (i.e. 34 => media)
$filters = array(
'media' => array(),
'industry' => array()
);
array_walk($tags, function($val, $key) use(&$filters) {
list($id, $type) = explode(',', $val);
$filters[$type][] = $id;
});
$portfolioItems = PortfolioItemPage::get()->filterAny(array(
'MediaTypeTags.ID' => $filters['media'],
'IndustryTags.ID' => $filters['industry']
));
$return = array();
foreach($portfolioItems as $portfolioItem){
$return[] = array(
'thumbnail' => $portfolioItem->Thumbnail()->Link(),
'name' => $portfolioItem->H1,
'logo' => $portfolioItem->Logo()->Link(),
'excerpt' => $portfolioItem->Excerpt,
'id' => $portfolioItem->ID
);
}
return json_encode($return);
}
I am adding a mass action to add a category. I am most of the way there I only have one function left to figure out.
Clr\Categorymassaction\controllers\Adminhtml\Catalog\ProductController.php
class Clr_Categorymassaction_Adminhtml_Catalog_ProductController extends Mage_Adminhtml_Controller_Action
{
public function massCategoryAction()
{
$productIds = $this->getRequest()->getParam('product');
$cat = $this->getRequest()->getParam('Category');
if (!is_array($productIds)) {
$this->_getSession()->addError($this->__('Please select product(s).'));
$this->_redirect('*/*/index');
}
else {
$cat = $category['label']->getCategoryId();
foreach($productIds as $product) {
//Process $cat into categoryId append categoryId to $productId
$cat->setPostedProducts($product);
}
//Save product
$cat->save();
}
}
}
Clr\Categorymassaction\Model\Observer
class Clr_Categorymassaction_Model_Observer {
public function addCategoryMassAction(Varien_Event_Observer $observer)
{
$block = $observer ->getBlock();
if ($block instanceof Mage_Adminhtml_Block_Catalog_Product_Grid) {
$block->getMassactionBlock()->addItem('Clr_Categorymassaction', array(
'label' => Mage::helper('catalog')->__('Add to Category'),
'url' => $block->getUrl('*/*/massCategory', array('_current' => true)),
'additional'=> array(
'visibility' => array(
'name' =>'Category',
'class' =>'required-entry',
'label' =>Mage::helper('catalog')->__('Categories'),
'type' => 'select',
'values' => Mage::getModel('Categorymassaction/system_config_source_category')->toOptionArray(),
'renderer' => 'Categorymassaction/catalog_product_grid_render_category',
)
)
));
};
}
}
One last thing
class Clr_Categorymassaction_Model_System_Config_Source_Category
{
public function toOptionArray($addEmpty = true)
{
$options = array();
foreach ($this->load_tree() as $category) {
$options[$category['value']] = $category['label'];
}
return $options;
}
I am mostly in trouble here because I am refactoring, Flagbit_changeattributeset and Vuleticd_AdminGridCategoryFilter. I know what I need to do (at least I think I do) I just don't know how to finish this off. Thanks for your eyes and ears if you read it all.
UPDATE: The observer from Vuleticd_AdminGridCategoryFilter had this additional code
'filter_condition_callback' => array($this, 'filterCallback'),
)
)
));
};
}
public function filterCallback($collection, $column)
{
$value = $column->getFilter()->getValue();
$_category = Mage::getModel('catalog/category')->load($value);
$collection->addCategoryFilter($_category);
return $collection;
}
This was used to apply the filter to the grid. What I am trying to do is instead of using the dropdown to filter column fields; use the dropdown to trigger the ProductController to pass the selected items a new categoryid.
https://magento.stackexchange.com/questions/67234/productcontroller-for-mass-action Asked this question over at magento's stackexchange figured I would post the link here for posterity.
I'm setting up pagination to display a list of images belonging to the user in their account. This is what I have in my controller:
class UsersController extends AppController {
public $paginate = array(
'limit' => 5,
'order' => array(
'Image.uploaded' => 'DESC'
)
);
// ...
public function images() {
$this->set('title_for_layout', 'Your images');
$albums = $this->Album->find('all', array(
'conditions' => array('Album.user_id' => $this->Auth->user('id'))
));
$this->set('albums', $albums);
// Grab the users images
$options['userID'] = $this->Auth->user('id');
$images = $this->paginate('Image');
$this->set('images', $images);
}
// ...
}
It works, but before I implemented this pagination I had a custom method in my Image model to grab the users images. Here it is:
public function getImages($options) {
$params = array('conditions' => array());
// Specific user
if (!empty($options['userID'])) {
array_push($params['conditions'], array('Image.user_id' => $options['userID']));
}
// Specific album
if (!empty($options['albumHash'])) {
array_push($params['conditions'], array('Album.hash' => $options['albumHash']));
}
// Order of images
$params['order'] = 'Image.uploaded DESC';
if (!empty($options['order'])) {
$params['order'] = $options['order'];
}
return $this->find('all', $params);
}
Is there a way I can use this getImages() method instead of the default paginate()? The closest thing I can find in the documentation is "Custom Query Pagination" but I don't want to write my own queries, I just want to use the getImages() method. Hopefully I can do that.
Cheers.
Yes.
//controller
$opts['userID'] = $this->Auth->user('id');
$opts['paginate'] = true;
$paginateOpts = $this->Image->getImages($opts);
$this->paginate = $paginateOpts;
$images = $this->paginate('Image');
//model
if(!empty($opts['paginate'])) {
return $params;
} else {
return $this->find('all', $params);
}
Explanation:
Basically, you just add another parameter (I usually just call it "paginate"), and if it's true in the model, instead of passing back the results of the find, you pass back your dynamically created parameters - which you then use to do the paginate in the controller.
This lets you continue to keep all your model/database logic within the model, and just utilize the controller to do the pagination after the model builds all the complicated parameters based on the options you send it.