Laravel error:: Illegal string offset 'category_name' - mysql

I'm trying to create an admin side form. Here i'm trying to select data from the database. Also i want to display it. But for some reason it's not working. Here's my controller code,
public function save()
{
if (Input::has('save'))
{
$rules = array('category_name' => 'required|min:1|max:50', 'parent_category' => 'required');
$input = Input::all();
$messages = array('category_name.required' =>'Please enter the category name.', 'category_name.min' => 'Category name must be more than 4 characters', 'category_name.max' =>'Category name must not be more than 15 characters!!!', 'parent_category.required' => 'Please Select Parent Category.',);
$validator = Validator::make($input, $rules, $messages);
if ($validator->fails())
{
return Redirect::to('admin/category/add')->withErrors($validator)->withInput($input);
}
else
{
$insert_db = CategoryModel::insert($input);
$selected_category = CategoryModel::select($input['category_name']);
}
}
}
and my CategoryModel.php is following.
public static function insert($values)
{
$insert = DB::table('add_category')->insert(array('category_name'=>$values['category_name'], 'parent_category'=>$values['parent_category']));
if(isset($insert))
{
echo 'inserted successfully';
}
else
{
echo 'Failed';
}
}
public static function select($values)
{
$insert = DB::table('add_category')->where('category_name' . '=' . $values['category_name']);
}

Related

How do I download a generated csv in magento 2.4.5

My files so far are:
system.xml
<field id="generate_csv" translate="label" type="button" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Generate Categories CSV</label>
<frontend_model>Vendor\Module\Block\Adminhtml\System\Config\Button</frontend_model>
</field>
button.php
<?php
namespace [Vendor]\[Module]\Block\Adminhtml\System\Config;
use Magento\Config\Block\System\Config\Form\Field;
use Magento\Backend\Block\Template\Context;
use Magento\Framework\Data\Form\Element\AbstractElement;
class Button extends Field
{
protected $_template = 'Vendor_Module::system/config/button.phtml';
public function __construct(
Context $context,
array $data = []
){
parent::__construct($context, $data);
}
public function render(AbstractElement $element)
{
$element->unsScope()->unsCanUseWebsiteValue()->unsCanUseDefaultValue();
return parent::render($element);
}
protected function _getElementHtml(AbstractElement $element)
{
return $this->_toHtml();
}
public function getAjaxUrl()
{
return $this->getUrl('[router]/Export/CategoryExport');
}
public function getButtonHtml()
{
$button = $this->getLayout()->createBlock(
'Magento\Backend\Block\Widget\Button'
)->setData(
[
'id' => 'generate_csv',
'label' => __('Generate CSV')
]
);
return $button->toHtml();
}
}
button.phtml
<script>
require([
'jquery',
'prototype'
], function ($) {
$('#generate_csv').click(function () {
var params = {};
new Ajax.Request('<?php echo $block->getAjaxUrl() ?>', {
parameters: params,
loaderArea: false,
asynchronous: true,
onCreate: function () {
$('#custom_button_response_message').text('');
},
onSuccess: function (transport) {
var resultText = '';
if (transport.status > 200) {
resultText = transport.statusText;
} else {
var response = JSON.parse(transport.responseText);
resultText = response.message
}
$('#generate_csv_response_message').text(resultText);
}
});
});
});
</script>
<?php echo $block->getButtonHtml(); ?>
<p>
<span id="generate_csv_response_message"></span>
</p>
controller
<?php
namespace [Vendor]\[Module]\Controller\Adminhtml\Export;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Controller\Result\Json;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Filesystem;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory;
use Magento\Catalog\Model\CategoryFactory;
class CategoryExport extends Action
{
protected $resultJsonFactory;
/**
* #param Context $context
* #param JsonFactory $resultJsonFactory
*/
public function __construct(
Context $context,
JsonFactory $resultJsonFactory,
Filesystem $filesystem,
DirectoryList $directoryList,
CollectionFactory $categoryCollectionFactory,
CategoryFactory $categoryFactory
){
$this->resultJsonFactory = $resultJsonFactory;
$this->filesystem = $filesystem;
$this->directory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR);
$this->categoryCollectionFactory = $categoryCollectionFactory;
$this->categoryFactory = $categoryFactory;
parent::__construct($context);
}
/**
* #return Json
*/
public function execute()
{
$message = 'Success';
$data[] = [
'id' => __('Entity ID'),
'name' => __('Name'),
'level' => __('Level')
];
$categoryCollection = $this->categoryCollectionFactory->create();
$categoryCollection->addAttributeToSelect('*');
$filepath = 'export/customerlist.csv';
$this->directory->create('export');
$stream = $this->directory->openFile($filepath, 'w+');
$stream->lock();
$header = ['Id', 'Name', 'Level'];
$stream->writeCsv($header);
//$categoryArray = array();
foreach ($categoryCollection as $category) {
$data = [];
$data[] = $category->getId();
$data[] = $category->getName();
$data[] = $category->getLevel();
$stream->writeCsv($data);
}
/** #var Json $result */
$result = $this->resultJsonFactory->create();
return $result->setData(['message' => $message]);
}
}
This creates a csv file in var/export directory but I cannot download it
Can anyone help explain how to modify the code so that it will automatically create and down the csv.
I have tried following various examples on the web but none of them have worked.
Please help me out

How can i insert data into two MySql tables on a single click?

How can i insert data into two MySql tables on a single click ?
model code
public function insertCSV($data)
{
$this->db->insert('question_tb', $data);
$this->db->insert('option_tb', $data);
return TRUE;
}
controller code
public function import(){
if (isset($_POST["import"])) {
$this->load->model('Welcome_model', 'welcome');
$exam_id = $this->welcome->get_max_exam_id();
$filename = $_FILES["file"]["tmp_name"];
if ($_FILES["file"]["size"] > 0) {
$file = fopen($filename, "r");
while (($importdata = fgetcsv($file, 10000, ",")) !== false) {
$data = [
'question' => $importdata[0],
'answer' => $importdata[1],
'exam_id' => $exam_id,
];
while (($importdata = fgetcsv($file, 10000, ",")) !== false) {
$data = [
'option1' => $importdata[2],
'option2' => $importdata[3],
'option3' => $importdata[4],
'exam_id' => $exam_id,
];
$insert = $this->welcome->insertCSV($data);
}
//fclose($file);
fclose($file);
redirect('upload/index');
}
}
}
}
There are two options
Create two functions in the model and call those function in the controller.
Model:
function a($data1){
$this->db->insert('table1', $data1);
}
function b($data2){
$this->db->insert('table2', $data2);
}
Controller :
function insert(){
$this->model_name->a($data1);
$this->model_name->b($data2);
}
Create a function in the model and pass two array data
Model:
function a($data1, $data2){
$this->db->insert('table1', $data1);
$this->db->insert('table2', $data2);
}
Controller:
function insert(){
$this->model_name->a($data1, $data2);
}

How to dynamically populate drop-down lists using Symfony forms?

I want to dynamically fill in my form (see picture)
countries states and cities
The states select (html tag) is populated with a json file by the javascript function :
function onChangeCountries(countries, states) {
$(countries).on("change", function(ev) {
var countryId = $(this).val();
if (countryId != '') {
states.empty();
states.append('<option selected="true" disabled>Choose state</option>');
states.prop('selectedIndex', 0);
$.getJSON(statesUrl, function (data) {
$.each(data['states'], function (key, entry) {
if (entry.country_id == countryId) {
states.append($('<option></option>').attr('value', entry.id).text(entry.name));
}
})
});
}
});
}
countries and states parameters correspond to the two firsts select.
This function populate the states select corresponding to the country selected. The same mechanism operates with the cities select.
Now I want to use Symfony 4, here is my form :
<?php
// src/Form/LocationType.php
namespace App\Form;
use App\Entity\Location;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class LocationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$countries = json_decode(file_get_contents("js/countries.json"), TRUE)['countries'];
$countriesChoices = array();
foreach($countries as $country) {
$countriesChoices[$country['name']] = $country['id'];
}
$states = json_decode(file_get_contents("js/states.json"), TRUE)['states'];
$statesChoices = array();
foreach($states as $state) {
$statesChoices[$state['name']] = $state['id'];
}
$cities = json_decode(file_get_contents("js/cities.json"), TRUE)['cities'];
$citiesChoices = array();
foreach($cities as $city) {
$citiesChoices[$city['name']] = $city['id'];
}
$builder
->add('country', ChoiceType::class, array(
'choices' => $countriesChoices
))
->add('area', ChoiceType::class, array(
'choices' => $statesChoices
))
->add('city', ChoiceType::class, array(
'choices' => array(
'Choose city' => $citiesChoices
))
->add('zip_code', TextType::class)
->add('street', TextType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Location::class,
));
}
}
The problem here is that I can not fill in the choices depending on user inputs.
Also I'm receiving an OutOfMemoryException (there is more than 40 000 cities in cities.json).
Edit
After dlondero answer, I haven't resolve my problem, here is my new LocationType class :
<?php
// src/Form/LocationType.php
namespace App\Form;
use App\Entity\Location;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class LocationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$countries = json_decode(file_get_contents("js/countries.json"), TRUE)['countries'];
$countriesChoices = array();
foreach($countries as $country) {
$countriesChoices[$country['name']] = $country['id'];
}
$builder
->add('zip_code', TextType::class)
->add('street', TextType::class)
->add('country', ChoiceType::class, array(
'choices' => $countriesChoices
))
->add('area', ChoiceType::class, array(
'choices' => array()
))
->add('city', ChoiceType::class, array(
'choices' => array()
))
;
$formModifierStates = function (FormInterface $form, $countryId = null) {
$statesChoices = array();
if (null !== $countryId) {
$states = json_decode(file_get_contents("js/states.json"), TRUE)['states'];
foreach($states as $state) {
if ($countryId == $state['country_id']) {
$statesChoices[$state['name']] = $state['id'];
}
}
}
$form->add('area', ChoiceType::class, array(
'choices' => $statesChoices
));
};
$formModifierCities = function (FormInterface $form, $stateId = null) {
$citiesChoices = array();
if (null !== $stateId) {
$cities = json_decode(file_get_contents("js/cities.json"), TRUE)['cities'];
foreach($cities as $city) {
if ($stateId == $city['state_id']) {
$citiesChoices[$city['name']] = $city['id'];
}
}
}
$form->add('city', ChoiceType::class, array(
'choices' => $citiesChoices
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifierStates) {
$data = $event->getData(); // country id
$formModifierStates($event->getForm(), $data);
}
);
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifierCities) {
$data = $event->getData(); // state id
$formModifierCities($event->getForm(), $data);
}
);
$builder->get('country')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifierStates) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$country = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifierStates($event->getForm()->getParent(), $country);
}
);
$builder->get('area')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifierCities) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$state = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifierCities($event->getForm()->getParent(), $state);
}
);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => Location::class,
));
}
}
After filling in the form, I've got the message : "The choice "..." does not exist or is not unique". The choice is refering to the id (value of option) of the city selected in the select.
The problem is that I can't figure out how to populate the city ChoiceType?
You'd need to load them dynamically based on the choice made for the previous select. Approach is a lot similar to your with JS.
You can see an example in the official documentation: Dynamic Generation for Submitted Forms.

Cakephp 2.61 and comboboxes

Using Cakephp 2.6.1, I have successfully captured and stored single characters in my database using the following code
echo $this->Form->input('grade', array('options' => array( 'G' => 'Good', 'P' => 'Pass','R'=>'Practice Required','F'=>'Fail')));
What I would like to know is how to convert these values back to the display values when retrieving them from the database, ie if the database contains 'P', I want to display 'Pass' in the view and index pages.
I'm certain the answer is simple and straightforward, and sheepishly apologise in advance for my ignorance.
Step-1
Create two new files under Vendor folder.
master-arrays.php
common-functions.php
and Import this two files
Process of import :
Dir : app\Config\bootstrap.php
Add this two lines:
App::import('Vendor', 'common-functions');
App::import('Vendor', 'master-arrays');
Step-2
Now open 'master-arrays.php'
and add this array
function grade_type()
{
$GRADE_TYPE['G'] = 'Good';
$GRADE_TYPE['P'] = 'Pass';
return $GRADE_TYPE;
}
Step-3
Change your view -
echo $this->Form->input('grade', array('options' =>grade_type())));
Step-4
Now add this function in 'common-functions.php'
function id_to_text($id, $arr_master=array()) {
$txt_selected = "";
$id = ''.$id; //Added this as it was creating some warnings online for wrong parameter types
if(is_array($arr_master) && array_key_exists($id,$arr_master)) {
$txt_selected = $arr_master[$id];
} else {
$txt_selected = "";
}
return $txt_selected;
}
Step-5
In Controller or in view
Input:
id_to_text('P',grade_type());
Output:
Pass
Try this,
// In controller
function fun()
{
$grade = array(
'G' => 'Good',
'P' => 'Pass',
'R' => 'Practice Required',
'F' => 'Fail'
);
$this->set('grade', $grade);
if ($this->request->data) {
$key = $this->request->data['Model']['grade'];
$this->request->data['Model']['grade'] = $grade[$key];
$this->Model->save($this->request->data);
}
}
// in view
echo $this->Form->input('grade', array(
'options' => $grade
));
Updated Code
// add in Model
function afterFind($results) {
foreach ($results as $key => $val) {
if (isset($val['MyModel']['status'])) {
$results[$key]['MyModel']['grade_text'] = $this->getGradeText($results[$key]['MyModel']['grade']);
}
}
return $results;
}
public function getGradeText($key)
{
$grades = array(
'G' => 'Good',
'P' => 'Pass',
'R' => 'Practice Required',
'F' => 'Fail'
);
$txt_selected = "";
if(array_key_exists($key,$grades)) {
$txt_selected = $grades[$key];
} else {
$txt_selected = "";
}
return $txt_selected;
}
// in controller
public function index() {
$this->set('data' , $this->paginate('MyModel'));
}
// in view
foreach($data as $value) {
echo $value['MyModel']['grade_text'];
}
I hope it will be help you.

fat models and thin controllers in codeigniter

this is a user.php controller
public function verifyLogin() {
if (isset($_POST["email"])) {
$e = $this->input->post("email");
$p = $this->input->post("pass");
$this->form_validation->set_rules("email", "email", "required|valid_email|xss_clean");
$this->form_validation->set_rules("pass", "password", "required|xss_clean");
if ($this->form_validation->run()) {
$data = array(
'select' => '*',
'table' => 'users',
'where' => "email = '$e' AND activated = '1'"
);
$checklogin = $this->query2->selectData($data);
if ($checklogin === FALSE) {
echo "quering userInfo fails. email is wrong or activation not done";
exit();
} else {
foreach ($checklogin as $row) {
$dbid = $row->id;
$dbusername = $row->username;
$dbpassword = $row->password;
$dbemail = $row->email;
if ($p === $dbpassword) {
$login_data = array(
'name' => $dbusername,
'email' => $dbemail,
'password' => $dbpassword,
'id' => $dbid,
'expire' => '86500',
'secure' => TRUE,
'logged_in' => TRUE
);
$this->input->set_cookie($login_data);
$this->session->set_userdata($login_data);
if ($this->session->userdata("logged_in")) {
$time = time();
$now = unix_to_human($time, TRUE, 'us');
$updateLogin = $this->query1->updateLogin($e, $now);
if ($updateLogin) {
echo "success";
} else {
echo 'update failed';
}
} else {
echo "session failed";
}
}else{
echo 'password incorrect';
}
}
}
} else {
echo "form validation fails";
}
} else {
$this->load->view('header');
$this->load->view('login');
$this->load->view('modal');
$this->load->view('footer');
}
}
this is model.php
public function selectData($data){
if(isset($data['direction'])){
$dir = $data['direction'];
}else{
$dir = "ASC";
}
if(isset($data['offset'])){
$off = $data['offset'];
}else{
$off = '0';
}
if(isset($data['select']) && isset($data['table'])){
$this->db->select($data['select'])->from($data['table']);
}
if(isset($data['where'])){
$this->db->where($data['where']);
}
if(isset($data['order_by_name'])){
$this->db->order_by($data['order_by_name'], $dir);
}
if(isset($data['limit'])){
$this->db->limit($data['limit'], $off);
}
$query = $this->db->get();
if($query){
$d = $query->result();
return $d;
}else{
return FALSE;
}
}
is this a good way of quering database?
i am new to mvc and i am reading everywhere about "fat models and this controllers"
what can be done to make it a good mvc architecture?
its only acceptable to echo out from the controller when you are developing:
if ($checklogin === FALSE) {
echo "quering userInfo fails.
if checking login is false then either show a view or go to a new method like
if ($checklogin === FALSE) {
$this->showLoginFailed($errorMessage) ;
the check login code in the controller is a great example of something that could be refactored to a model. then if you need to check login from another controller its much easier. putting the form validation code in a model would be another choice. often times when you are validating form code you are also inserting/updating to a database table -- so having all those details together in a model can make things easier long term.
"fat model" does not mean one method in a model that does a hundred things. it means the controller says -- did this customer form validate and insert to the database? yes or no? 3 lines of code.
the model has the code that is looking into the "fat" details of the form, validation, database, etc etc. say 50 or more lines compared to the 3 in the controller. but the methods in the model should still be clean: small and specific.