I found similar topics, but they are not up to date.
I have to generate around 1000 orders with random products. I found good article about creating orders http://inchoo.net/magento/programmatically-create-order-in-magento/ but it's kinda old and it's not working on version 1.9.
I get following errors:
array (size=5)
0 => string 'Please specify the product's option(s).' (length=39)
1 => string 'Please specify the product's option(s).' (length=39)
2 => string 'Please specify the product's option(s).' (length=39)
3 => string 'Please specify the product's option(s).' (length=39)
4 => string 'Please specify the product's option(s).' (length=39)
#0 E:\xampp\htdocs\magento\app\code\core\Mage\Adminhtml\Model\Sales\Order\Create.php(1631): Mage::throwException('')
#1 E:\xampp\htdocs\magento\app\code\core\Mage\Adminhtml\Model\Sales\Order\Create.php(1523): Mage_Adminhtml_Model_Sales_Order_Create->_validate()
As you can see in my create method I add options to product, so why do I get this errors?
Here is my class
class MyNamespace_MyModule_Model_Generate_Sample {
protected $orderData;
protected $product;
public function run()
{
//$customer is a random customer object
$product = Mage::getModel('catalog/product')->load(342);
$this->product = $product;
$this->orderData = array(
'session' => array(
'customer_id' => $customer->getId(),
'store_id' => Mage::app()->getStore('default')->getId(),
),
'payment' => array(
'method' => 'checkmo',
),
'add_products' =>array(
$product->getId() => array('qty' => 1),
),
'order' => array(
'currency' => 'USD',
'account' => array(
'group_id' => $customer->getGroupId(),
'email' => $customer->getEmail()
),
'billing_address' => array(
'customer_address_id' => $customer->getCustomerAddressId(),
'prefix' => '',
'firstname' => $customer->getFirstname(),
'middlename' => '',
'lastname' => $customer->getLastname(),
'suffix' => '',
'company' => '',
'street' => array($customer->getStreet(),''),
'city' => $customer->getCity(),
'country_id' => $customer->getCountryId(),
'region' => '',
'region_id' => $customer->getRegionId(),
'postcode' => $customer->getPostcode(),
'telephone' => $customer->getTelephone(),
'fax' => '',
),
'shipping_address' => array(
'customer_address_id' => $customer->getCustomerAddressId(),
'prefix' => '',
'firstname' => $customer->getFirstname(),
'middlename' => '',
'lastname' => $customer->getLastname(),
'suffix' => '',
'company' => '',
'street' => array($customer->getStreet(),''),
'city' => $customer->getCity(),
'country_id' => $customer->getCountryId(),
'region' => '',
'region_id' => $customer->getRegionId(),
'postcode' => $customer->getPostcode(),
'telephone' => $customer->getTelephone(),
'fax' => '',
),
'shipping_method' => 'flatrate_flatrate',
'comment' => array(
'customer_note' => 'This order has been programmatically created via import script.',
),
'send_confirmation' => 0
),
);
$this->create();
}
/**
* Creates order
*/
public function create()
{
$orderData = $this->orderData;
if (!empty($orderData)) {
$this->_initSession($orderData['session']);
$this->_processQuote($orderData);
if (!empty($orderData['payment'])) {
$this->_getOrderCreateModel()->setPaymentData($orderData['payment']);
$this->_getOrderCreateModel()->getQuote()->getPayment()->addData($orderData['payment']);
}
$item = $this->_getOrderCreateModel()->getQuote()->getItemByProduct($this->product);
foreach($this->product->getAttributes() as $option)
{
if ($option->getIsVisibleOnFront()) {
$item->addOption(new Varien_Object(
array(
'product' => $this->product,
'code' => $option->getAttributeCode(),
'value' => $option->getFrontend()->getValue($this->product)
)
));;
}
}
Mage::app()->getStore()->setConfig(Mage_Sales_Model_Order::XML_PATH_EMAIL_ENABLED, "0");
$_order = $this->_getOrderCreateModel()
->importPostData($orderData['order'])
->createOrder();
$this->_getSession()->clear();
Mage::unregister('rule_data');
return $_order;
}
return null;
}
protected function _processQuote($data = array())
{
/* Saving order data */
if (!empty($data['order'])) {
$this->_getOrderCreateModel()->importPostData($data['order']);
}
$this->_getOrderCreateModel()->getBillingAddress();
$this->_getOrderCreateModel()->setShippingAsBilling(true);
/* Just like adding products from Magento admin grid */
if (!empty($data['add_products'])) {
$this->_getOrderCreateModel()->addProducts($data['add_products']);
}
/* Collect shipping rates */
$this->_getOrderCreateModel()->collectShippingRates();
/* Add payment data */
if (!empty($data['payment'])) {
$this->_getOrderCreateModel()->getQuote()->getPayment()->addData($data['payment']);
}
$this->_getOrderCreateModel()
->initRuleData()
->saveQuote();
if (!empty($data['payment'])) {
$this->_getOrderCreateModel()->getQuote()->getPayment()->addData($data['payment']);
}
return $this;
}
/**
* Retrieve order create model
*
* #return Mage_Adminhtml_Model_Sales_Order_Create
*/
protected function _getOrderCreateModel()
{
return Mage::getSingleton('adminhtml/sales_order_create');
}
/**
* Retrieve session object
*
* #return Mage_Adminhtml_Model_Session_Quote
*/
protected function _getSession()
{
return Mage::getSingleton('adminhtml/session_quote');
}
/**
* Initialize order creation session data
*
* #param array $data
* #return Mage_Adminhtml_Sales_Order_CreateController
*/
protected function _initSession($data)
{
/* Get/identify customer */
if (!empty($data['customer_id'])) {
$this->_getSession()->setCustomerId((int) $data['customer_id']);
}
/* Get/identify store */
if (!empty($data['store_id'])) {
$this->_getSession()->setStoreId((int) $data['store_id']);
}
return $this;
}
}
Thanks for any help
Related
How can I get data from another table?
// ServiceComplexController
public function index(Store $store): JsonResponse
{
/* #var User $user */
$user = auth()->user();
$this->listQuery = $user->store->serviceComplexes()->getQuery();
return response()->json([
'data' => StoreServiceComplexResource::collection($this->listQuery->get()),
]);
}
// StoreServiceComplexResource
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
'base_service_ids' => $this->base_service_ids,
'more_service_ids' => $this->more_service_ids,
];
}
// Dump $this->listQuery->get()
array (
0 =>
array (
'id' => 3,
'name' => 'Complex 1',
'description' => 'Desc complex 1',
'base_service_ids' =>
array (
0 => 1,
1 => 2,
),
'more_service_ids' =>
array (
0 => 10,
),
),
)
How to get base services from another table(services) based on field "base_service_ids" and "more_service_ids" and add them to response ?
Is it possible to give this data also through Collection Resource ? For example
// StoreServiceComplexResource
public function toArray($request): array
{
return [
...
'service' => [] //StoreServiceResource::collection() ....
...
];
}
I tried to validate a simple form in zend framework 2 for days now.
I checked the documentation and a lot of posts considering this topic but I found no solution!
I have a very simple form:
class AlimentForm extends Form
{
public function __construct($name = null)
{
parent::__construct('aliment');
$this->add(array(
'required'=>true,
'name' => 'year',
'type' => 'Text',
'options' => array(
'label' => 'Jahr',
),
));
$this->add(array(
'required'=>true,
'name' => 'number',
'type' => 'Text',
'options' => array(
'label' => 'Number',
),
));
$this->add(array(
'name' => 'submit',
'type' => 'Submit',
'attributes' => array(
'value' => 'Go',
'id' => 'submitbutton',
),
));
}
}
I created a custom InputFilter:
namespace Application\Form;
use Zend\InputFilter\InputFilter;
class AlimentInputFilter extends InputFilter {
public function init()
{
$this->add([
'name' => AlimentForm::year,
'required' => true,
'validators' => array(
array(
'name' => 'Between',
'options' => array(
'min' => 1900,
'max' => 3000,
),
),
),
]);
}
}
and finally in my controller I try to validate the form
public function alimentAction(){
$form = new AlimentForm();
$form->setInputFilter(new AlimentInputFilter());
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$year = $form->get('year')->getValue();
$number = $form->get('number')->getValue();
return array('result' => array(
"msg" => "In the Year ".$year." you get ".$number." Points"
));
}
}
return array('form' => $form);
}
It can't be that difficult, but from all those different ways to validate a form I found in the net, I'm a bit confused...
What am I missing?
Greetings and thanks in advance
U.H.
Ok, I solved the problem.
I created a Model for the aliment Form that has a year and a number attribute
and I defined an input filter within that model:
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
class Aliment implements InputFilterAwareInterface
{
public $year;
public $number;
public function exchangeArray($data){
$this->year = (!empty($data['year']))?$data['year']:null;
$this->number = (!empty($data['number']))?$data['number']:null;
}
public function setInputFilter(InputFilterInterface $inputFilter)
{
throw new \Exception("Not used");
}
public function getInputFilter()
{
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$inputFilter->add(array(
'name' => 'year',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'Between',
'options' => array(
'min' => 1900,
'max' => 3000
)
)
),
));
$inputFilter->add(array(
'name' => 'number',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'Between',
'options' => array(
'min' => 1,
'max' => 10
)
)
),
));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
}
In the action method of the controller I was able to set the InputFilter of the model to the form and voila! It worked!
public function alimentAction(){
$form = new AlimentForm();
$request = $this->getRequest();
if ($request->isPost()) {
$aliment = new \Application\Model\Aliment;
$form->setInputFilter($aliment->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$aliment->exchangeArray($form->getData());
$year = $form->get('year')->getValue();
return array(
'result' => array(
//your result
)
);
}
}
return array('form' => $form);
}
The form is correctly validated now and returns the corresponding error messages.
I hope, it help somebody whos got similar problems with validating!
In my symfony application, I use voters to check if users can access some features.
Now, I have a navbar where the menus are displayed or hidden according to those rights.
This navbar alone renders in about 2 seconds. That's a lot added to every page.
If I comment out the render_controller of the navbar, I gain 2 seconds. If I return true at the top of every voter is_granted method, I gain 1.5 seconds.
How can I solve this ? Using cache ? not using voters ? simplifying my voters ? Is it not a best practice to use voters? even if symfony has to check attributes against the list of all attributes?
My navbar generator:
<?php
namespace AppBundle\Menu;
use AppBundle\Application\Core\ExplorerManager;
use AppBundle\Entity\User\Associate;
use AppBundle\Entity\User\Role;
use Symfony\Component\Routing\Router;
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
use Symfony\Component\Translation\Translator;
class MenuBuilder
{
/**
* #var Router
*/
private $router;
/**
* #var Translator
*/
private $translator;
/**
* #var AuthorizationChecker
*/
private $authorizationChecker;
/**
* #param Router $router
* #param Translator $translator
* #param AuthorizationChecker $authorizationChecker
*/
public function __construct(Router $router, Translator $translator, AuthorizationChecker $authorizationChecker)
{
$this->router = $router;
$this->translator = $translator;
$this->authorizationChecker = $authorizationChecker;
}
public function getFrontendHeaderMenuItems($isAuthenticated)
{
$menuItems = array(
array(
'title' => 'pricing',
'route' => 'cms',
'route_parameters' => array('dir' => 'general', 'page' => 'foodmeup_premium')
),
// array(
// 'title' => 'recipes',
// 'route' => 'explore',
// 'route_parameters' => array('object' => ExplorerManager::RECETTE)
// ),
array(
'title' => 'blog',
'route' => 'explore',
'route_parameters' => array('object' => ExplorerManager::BLOG)
),
array(
'title' => 'contact',
'route' => 'message_foodmeup'
)
);
if (false == $isAuthenticated) {
$menuItems[] = array(
'title' => 'login',
'route' => 'login'
);
}
$menuItems = $this->generateMenuRoutes(
$menuItems,
'frontend_bars',
array()
);
return $menuItems;
}
public function getBackendLeftSidebarMenuItems()
{
$menuItems = array(
array(
'title' => 'dashboard',
'icon' => 'th-large',
'route' => 'dashboard'
),
array(
'title' => 'administration',
'icon' => 'star',
'is_granted' => Role::ROLE_ADMIN,
'children' => array(
array(
'title' => 'dashboard',
'route' => 'admin_dashboard',
),
array(
'title' => 'moderation',
'route' => 'moderate_posts',
),
array(
'title' => 'users',
'route' => 'switch_user',
'is_granted' => Role::ROLE_SUPERADMIN,
),
array(
'title' => 'subscriptions',
'route' => 'grant_partner_subscription',
'is_granted' => Role::ROLE_SUPERADMIN,
)
)
), array(
'title' => 'ingredients',
'icon' => 'flask',
'children' => array(
array(
'title' => 'explore_ingredients',
'route' => 'explore',
'route_parameters' => array('object' => ExplorerManager::CONSOMMABLE)
),
array(
'title' => 'my_ingredients',
'route' => 'user_ingredients_display',
'is_granted' => Associate::READ_INGREDIENT
), array(
'title' => 'create_import',
'route' => 'edit_ingredient',
'is_granted' => Associate::EDIT_INGREDIENT
), array(
'title' => 'stock',
'route' => 'set_ingredient_stock',
'is_granted' => Associate::READ_STOCK,
), array(
'title' => "buying_cost",
'route' => 'parameter_cost',
'is_granted' => Associate::READ_COST,
)
)
), array(
'title' => 'recipes',
'icon' => 'birthday-cake',
'children' => array(
array(
'title' => 'explore_recipes',
'route' => 'explore',
'route_parameters' => array('object' => ExplorerManager::RECETTE)
),
array(
'title' => 'my_recipes',
'route' => 'user_recipes_display',
'is_granted' => Associate::READ_RECIPE
), array(
'title' => 'create',
'route' => 'edit_recipe',
'is_granted' => Associate::EDIT_RECIPE
), array(
'title' => 'print',
'route' => 'print_recipes',
'is_granted' => Associate::READ_RECIPE
)
)
), array(
'title' => 'plannings',
'icon' => 'tasks',
'is_granted' => array(Associate::READ_PLANNING, Associate::EDIT_PLANNING, Associate::DELETE_PLANNING),
'children' => array(
array(
'title' => 'my_plannings',
'route' => 'display_plannings',
'is_granted' => Associate::READ_PLANNING
), array(
'title' => 'my_models',
'route' => 'display_plannings',
'route_parameters' => array('isModel' => true),
'is_granted' => Associate::READ_PLANNING
), array(
'title' => 'create_planning',
'route' => 'edit_planning',
'is_granted' => array(Associate::EDIT_PLANNING, Associate::CREATE_MODEL)
)
)
), array(
'title' => 'orders',
'icon' => 'phone',
'is_granted' => array(Associate::READ_ORDER, Associate::EDIT_ORDER, Associate::EDIT_ORDER, Associate::DELETE_ORDER),
'children' => array(
array(
'title' => 'my_orders',
'route' => 'display_planning_orders',
'is_granted' => Associate::READ_ORDER
), array(
'title' => 'automatic_order',
'route' => 'automatic_order',
'is_granted' => Associate::EDIT_ORDER
), array(
'title' => 'edit_order',
'route' => 'edit_order',
'is_granted' => Associate::EDIT_ORDER
)
)
), array(
'title' => 'suppliers',
'icon' => 'truck',
'is_granted' => array(Associate::EDIT_SUPPLIER, Associate::READ_SUPPLIER, Associate::DELETE_SUPPLIER),
'children' => array(
array(
'title' => 'my_suppliers',
'route' => 'display_suppliers',
'is_granted' => Associate::READ_SUPPLIER
), array(
'title' => 'select',
'route' => 'user_supplier_select',
'is_granted' => Associate::EDIT_SUPPLIER
), array(
'title' => 'create',
'route' => 'edit_organization',
'route_parameters' => array('category_slug' => 'fournisseur-de-consommables'),
'is_granted' => Associate::EDIT_SUPPLIER
)
)
), array(
'title' => 'teams',
'icon' => 'users',
'is_granted' => array(Associate::EDIT_TEAM, Associate::READ_TEAM, Associate::DELETE_TEAM, Associate::MANAGE_RIGHTS),
'children' => array(
array(
'title' => 'my_teams',
'route' => 'teams_display',
), array(
'title' => 'worker_parameter',
'route' => 'worker_parameter',
'is_granted' => Associate::EDIT_TEAM,
)
)
)
);
$menuItems = $this->generateMenuRoutes($menuItems, 'backend_bars', array());
return $menuItems;
}
private function generateMenuRoutes(Array $menuItems, $domain, $isGranted)
{
foreach ($menuItems as $key => $menuItem) {
if (array_key_exists('is_granted', $menuItems[$key])) {
$rights = is_array($menuItems[$key]['is_granted']) ? $menuItems[$key]['is_granted'] : array($menuItems[$key]['is_granted']);
$rights = array_map(function ($right) {
return $this->authorizationChecker->isGranted($right);
}, $rights);
if (in_array(true, $rights) == false) {
unset($menuItems[$key]);
continue;
}
}
if (array_key_exists('route', $menuItems[$key])) {
$menuItems[$key]['uri'] = $this->router->generate($menuItems[$key]['route'], array_key_exists('route_parameters', $menuItems[$key]) ? $menuItems[$key]['route_parameters'] : array());
} else {
$menuItems[$key]['uri'] = '#/';
}
$menuItems[$key]['title'] = $this->translator->trans($menuItems[$key]['title'], array(), $domain);
if (array_key_exists('children', $menuItems[$key])) {
$menuItems[$key]['children'] = $this->generateMenuRoutes($menuItems[$key]['children'], $domain, $isGranted);
}
}
return $menuItems;
}
public function extractTitles(Array $menuItems)
{
$titles = array();
foreach ($menuItems as $key => $menuItem) {
$titles[] = $menuItems[$key]['title'];
if (array_key_exists('children', $menuItems[$key])) {
$titles = array_merge($titles, $this->extractTitles($menuItems[$key]['children']));
}
}
return $titles;
}
}
Voters have performance drawbacks. So if you need a higher performance then it's better to use ACL or optimize voters loading, because symfony loops over all voters when each security check is performed.
Lets's suppose you have 30 links in a menu and there are 20 voters. When you check access to all links in 1 loop then symfony will call voters 600 times (the most of them will return Voter::ACCESS_ABSTAIN immediately, but it still takes time and in you case it takes too much time).
Update:
Symfony added voter caching for skipping call unneeded voters if new functions supportsAttribute or supportsType returned false once.
https://symfony.com/blog/new-in-symfony-5-4-faster-security-voters
Copy Ordered.php
From
app/code/core/Mage/Adminhtml/Block/Dashboard/Tab/Products
to
app/code/local/Mage/Adminhtml/Block/Dashboard/Tab/Products
Rename New.php
I have modified the following code:
class Mage_Adminhtml_Block_Dashboard_Tab_Products_New extends Mage_Adminhtml_Block_Dashboard_Grid
{
public function __construct()
{
parent::__construct();
$this->setId('productsNewGrid');
}
protected function _prepareCollection()
{
if (!Mage::helper('core')->isModuleEnabled('Mage_Sales')) {
return $this;
}
if ($this->getParam('website')) {
$storeIds = Mage::app()->getWebsite($this->getParam('website'))->getStoreIds();
$storeId = array_pop($storeIds);
} else if ($this->getParam('group')) {
$storeIds = Mage::app()->getGroup($this->getParam('group'))->getStoreIds();
$storeId = array_pop($storeIds);
} else {
$storeId = (int)$this->getParam('store');
}
$todayStartOfDayDate = Mage::app()->getLocale()->date()
->setTime('00:00:00')
->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);
$todayEndOfDayDate = Mage::app()->getLocale()->date()
->setTime('23:59:59')
->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);
$collection = Mage::getResourceModel('catalog/product_collection');
$collection->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());
$collection
->addStoreFilter()
->addAttributeToFilter('news_from_date', array('or'=> array(
0 => array('date' => true, 'to' => $todayEndOfDayDate),
1 => array('is' => new Zend_Db_Expr('null')))
), 'left')
->addAttributeToFilter('news_to_date', array('or'=> array(
0 => array('date' => true, 'from' => $todayStartOfDayDate),
1 => array('is' => new Zend_Db_Expr('null')))
), 'left')
->addAttributeToFilter(
array(
array('attribute' => 'news_from_date', 'is'=>new Zend_Db_Expr('not null')),
array('attribute' => 'news_to_date', 'is'=>new Zend_Db_Expr('not null'))
)
);
$this->setCollection($collection);
return parent::_prepareCollection();
}
protected function _prepareColumns()
{
$this->addColumn('name', array(
'header' => $this->__('Product Name'),
'sortable' => false,
'index' => 'product_name'
));
$this->addColumn('price', array(
'header' => $this->__('Price'),
'width' => '120px',
'type' => 'currency',
'currency_code' => (string) Mage::app()->getStore((int)$this->getParam('store'))->getBaseCurrencyCode(),
'sortable' => false,
'index' => 'product_price'
));
$this->addColumn('ordered_qty', array(
'header' => $this->__('Quantity Ordered'),
'width' => '120px',
'align' => 'right',
'sortable' => false,
'index' => 'qty_ordered',
'type' => 'number'
));
$this->setFilterVisibility(false);
$this->setPagerVisibility(false);
return parent::_prepareColumns();
}
/*
* Returns row url to show in admin dashboard
* $row is bestseller row wrapped in Product model
*
* #param Mage_Catalog_Model_Product $row
*
* #return string
*/
public function getRowUrl($row)
{
// getId() would return id of bestseller row, and product id we get by getProductId()
$productId = $row->getProductId();
// No url is possible for non-existing products
if (!$productId) {
return '';
}
$params = array('id' => $productId);
if ($this->getRequest()->getParam('store')) {
$params['store'] = $this->getRequest()->getParam('store');
}
return $this->getUrl('*/catalog_product/edit', $params);
}
}
Then Copy Grids.php
From
app/code/core/Mage/Adminhtml/Block/Dashboard/
to
app/code/local/Mage/Adminhtml/Block/Dashboard/
added the following code:
$this->addTab('new_products', array(
'label' => $this->__('New Product'),
'content' => $this->getLayout()->createBlock('adminhtml/dashboard_tab_products_new')->toHtml(),
'class' => 'ajax'
));
I want to add a new product tab in admin dashboard,beside customers.I don't know what wrong with the New.php.I click the new product tab,it's not working.How to fix it?
I have managed to get this working with only a few more lines to change.
Update the Dashboard controller Mage_Adminhtml_DashboardController to add the new action
public function productsNewAction()
{
$this->loadLayout();
$this->renderLayout();
}
Update the admin layout.xml design\adminhtml\default\default\layout\main.xml to add the new section
<adminhtml_dashboard_productsnew>
<block type="core/text_list" name="root" output="toHtml">
<block type="adminhtml/dashboard_tab_products_new" name="adminhtml.dashboard.tab.products.new"/>
</block>
</adminhtml_dashboard_productsnew>
The you would just need to update your code in the Grids.php to the following.
$this->addTab('new_products', array(
'label' => $this->__('New Product'),
'url' => $this->getUrl('*/*/productsNew', array('_current'=>true)),
'class' => 'ajax'
));
This should then work using a call to the url rather than the block content.
You then need to select the attributes you want to show. You can do this by selecting all or by attribute code.
$collection->addAttributeToSelect('*')
$collection->addAttributeToSelect('name');
Important is the column index defined in _prepareColumns match these attribute codes Otherwise you will just get an empty row.
I would suggest packaging these changes into a new module with a controller, layout.xml and block files. There are lots of great tutorials around on how to do this, but obviously you don't have to :)
I'm trying to working with the Uploader Plugin to create a structure where a User Model can upload it's avatar with the Avatar Model, I've read the instructions several times but when I try to $this->Uploader->upload('Avatar.filename') I get no validation errors but the upload method fails.
Here is how I've written the User Model
<?php
class User extends AppModel {
public $name = 'User';
public $hasOne = array(
'Profile' => array(
'className' => 'Profile',
'conditions' => '',
'dependent' => true,
'foreignKey' => 'user_id',
'associatedKey' => 'user_id'
),
'Avatar' => array (
'className' => 'Avatar',
'foreignKey' => 'user_id',
'dependent' => true
)
);
public $validate = array(...);
// other stuff not relevant here...
?>
Here is the Avatar Model
<?php
class Avatar extends AppModel {
public $name = 'Avatar';
public $actsAs = array (
'Uploader.Attachment' => array (
'Avatar.filename' => array(
'name' => 'setNameAsImgId', // Name of the function to use to format filenames
'baseDir' => '', // See UploaderComponent::$baseDir
'uploadDir' => 'files/avatars/', // See UploaderComponent::$uploadDir
'dbColumn' => 'filename', // The database column name to save the path to
'importFrom' => '', // Path or URL to import file
'defaultPath' => '', // Default file path if no upload present
'maxNameLength' => 500, // Max file name length
'overwrite' => true, // Overwrite file with same name if it exists
'stopSave' => true, // Stop the model save() if upload fails
'allowEmpty' => true, // Allow an empty file upload to continue
'transforms' => array (
array('method' => 'resize', 'width' => 128, 'height' => 128, 'dbColumn' => 'name')
) // What transformations to do on images: scale, resize, ete
)
),
'Uploader.FileValidation' => array (
'Avatar.filename' => array (
'maxWidth' => array (
'value' => 512,
'error' => 'maxWidth error'
),
'maxHeight' => array (
'value' => 512,
'error' => 'maxWidth error'
),
'extension' => array (
'value' => array('gif', 'jpg', 'png', 'jpeg'),
'error' => 'extension error'
),
'filesize' => array (
'value' => 5242880,
'error' => 'filesize error'
)
)
)
);
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
'conditions' => '',
'order' => ''
)
);
public function setNameAsImgId ($name, $field, $file) {
/**
* Format the filename a specific way before uploading and attaching.
*
* #access public
* #param string $name - The current filename without extension
* #param string $field - The form field name
* #param array $file - The $_FILES data
* #return string
*/
// devo ricavare l'id dell'immagine appena creata per rinominare il file
return $name;
}
}
?>
This is the UsersController for edit method
<?php
App::uses('CakeEmail','Network/Email');
CakePlugin::load('Uploader');
App::import('Vendor', 'Uploader.Uploader');
class UsersController extends AppController {
public $name = 'Users';
public function edit ($id) {
$this->User->id = $id;
if (!$this->User->exists()) {
throw new NotFoundException ('Nessuna corrispondenza trovata per questo utente');
}
if (!$id) {
$this->set('flash_element','error');
$this->Session->setFlash ('Utente non valido');
}
$this->User->recursive = 1;
$this->set('user', $this->User->read());
if ($this->request->is('post')) {
$this->User->id = $this->request->data['User']['id'];
if (!$this->User->exists()) {
$this->set('flash_element','warning');
$this->Session->setFlash('Nessun utente trovato con questa corrispondenza');
}
if ($this->User->save($this->request->data)) {
$this->request->data['Profile']['user_id'] = $this->User->id;
$conditions = array(
'conditions' => array(
'Profile.id' => $this->request->data['Profile']['id']
)
);
if ($this->User->Profile->save($this->request->data, $conditions)) {
if (!empty($this->request->data['Avatar']['filename'])) {
$this->request->data['Avatar']['user_id'] = $this->User->id;
if ($this->User->Avatar->save($this->request->data)) {
$avatar = $this->User->Avatar->find('first', array(
'conditions' => array('Avatar.user_id' => $this->User->id)
));
$ext = Uploader::ext($this->request->data['Avatar']['filename']);
$filename = $avatar['Avatar']['id'].'.'.$ext;
if ($this->User->Avatar->save('Avatar.filename')) {
$this->set('flash_element','done');
$this->Session->setFlash('Avatar changed successfully');
debug('saved successfully');
} else {
debug('not saved');
$this->set('flash_element','warning');
$this->Session->setFlash('Avatar not saved on the server');
}
} else {
$this->Session->write('flash_element','error');
$this->Session->setFlash('Avatar data not saved on the server');
$this->redirect(array('action'=>'index'));
}
} else {
$this->Session->write('flash_element','done');
$this->Session->setFlash('Data successfully saved, avatar not changed');
$this->redirect(array('action'=>'index'));
}
} else {
$this->set('flash_element','error');
$this->Session->setFlash('Error on saving Profile data to the server');
}
} else {
$this->Session->write('flash_element','error');
$this->Session->setFlash('Error on saving User data to the server');
$this->redirect(array('action'=>'index'));
}
}
}
}
?>
And in the view file I have this
<?php
echo $this->Form->create('User', array ('class' => 'form'));
echo $this->Form->input('User.id', array ('type'=>'hidden', 'value'=> $user['User']['id'],'label'=> false, 'id' => 'id'));
echo $this->Form->input('User.username', array ('label'=> false, 'value' => $user['User']['username'], 'id' => 'username', 'after' => '<div class="message">Message for username field'));
echo $this->Form->input('User.email', array ('label'=> false, 'value' => $user['User']['email'], 'id' => 'email', 'after' => '<div class="message">Message for email field</div>'));
echo $this->Form->input('UserOptions.id', array ('type'=>'hidden', 'value'=> $user['UserOptions']['id'],'label'=> false, 'id' => 'UserOptions.id'));
$attributes = array ('value' => $user['UserOptions']['avatar_type'], 'empty' => false);
$options = array('0' => 'This site', '1' => 'Gravatar');
echo $this->Form->select('UserOptions.avatar_type', $options, $attributes);
/* avatar code */
echo $this->Form->input('Avatar.id', array ('type'=>'hidden', 'value'=> $user['Avatar']['id'],'label'=> false, 'id' => 'Avatar.id'));
echo $this->Form->input('Avatar.filename', array('type' => 'file'));
/* end avatar code */
echo $this->Form->input('Profile.city', array ('label'=> false, 'value' => defaultValue ('City', $user['Profile']['city']), 'id' => 'city', 'after' => '<div class="message">Message for city field</div>'));
echo $this->Form->input('Profile.country', array ('label'=> false, 'value' => defaultValue('',$user['Profile']['country']), 'id' => 'country', 'after' => '<div class="message">Message for country field</div>'));
echo $this->Form->input('Profile.url', array ('label'=> false, 'value' => defaultValue('http://', $user['Profile']['url']), 'id' => 'url', 'after' => '<div class="message">Message for url field</div>'));
echo $this->Form->input('Profile.description', array ('label'=> false, 'value' => defaultValue('Description',$user['Profile']['description']), 'id' => 'description', 'after' => '<div class="message">Message for description field</div>'));
echo $this->Form->submit('Modifica', array('id'=>'edit'));
echo $this->Form->end();
?>
In the Controller, every part of the data is saved until I reach $this->Uploader->upload('Avatar.filename', array('overwrite' => true, 'name' => $filename)) where I get a generic error.
This Plugin seems to be the best way to do it without write tons of code, but I'm not sure how to use it.
I'm not sure what's wrong with the code, can You help me to solve the problem?
I've found the problems, I forgot two things:
In the view page I've forgot 'type' => 'file'
<?php
echo $this->Form->create('User', array ('class' => 'form', 'type' => 'file'));
?>
I was used to work with 1.3 version so the app/Config/bootstrap.php configuration was missing:
<?php
CakePlugin::load('Uploader');
?>
Now it works!