Yii: Update model values before actionCreate and actionUpdate - post

I have a Location model with the following attributes -
id
City
State
Country
I wan't the user to be able to select from a list of existing states / countries, and if an additional item needs to be added it may be typed into a textbox. I've modified the _form.php partial as follows -
// city
<?php echo $form->textField($model,'city',array('size'=>60,'maxlength'=>100)); ?>
// state
<?php echo $form->dropDownList($model, 'state', CHtml::listData(Location::model()->findAll(), 'state', 'state')); ?>
<?php echo CHtml::textField('state2','',array('size'=>60,'maxlength'=>100)); ?>
// country
<?php echo $form->dropDownList($model, 'country', CHtml::listData(Location::model()->findAll(), 'country', 'country')); ?>
<?php echo CHtml::textField('country2','',array('size'=>60,'maxlength'=>100)); ?>
state2 and country2 are not a part of the model attributes. Now, in the Location Controller I have the following action -
public function actionCreate()
{
$model=new Location;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Location']))
{
$model->attributes=$_POST['Location'];
if($model->save())
$this->redirect(array('view','id'=>$model->id));
}
$this->render('create',array(
'model'=>$model,
));
}
I want to set the values like this before this action executes -
if(!empty($_POST['state2'])) $model->state = $_POST['state2'];
if(!empty($_POST['country2'])) $model->country = $_POST['country2'];
What I've tried so far
1. Attempt 1
I added the lines directly to both actionCreate and actionUpdate. However, I don't think this is a clean solution.
1. Attempt 2
I tried adding a filter like this -
public function filterAlternateData($filterChain)
{
if(!empty($_POST['state2'])) $_POST['Location[state]'] = $_POST['state2'];
if(!empty($_POST['country2'])) $_POST['Location[country]'] = $_POST['country2'];
$filterChain->run();
}
Then I modified the filters() function like this so that it's bound to the create and update actions -
public function filters()
{
return array(
'accessControl', // perform access control for CRUD operations
'alternateData + create, update',
);
}
But this did not work.
Anyone have any ideas?

I presume this is happening in a CRUD operation based upon the actionCreate() method.
Personally I would create a separate form for the create functionality with the following attributes.
Form
Cities
States
Countries
New city (not required)
New State (not required)
New Country (not required)
Then in the form validation you can check to see if the user has entered a city, state or country which already exists etc.

You can add the lines in beforeSave() method (you will have to override it) of your model.

Related

How to edit an image in laravel 5 if user upload a new one ,otherwise upload with old image file

I have an edit form which has an image field where a user can upload a new image if he wants to.
But if the user does not upload a new photo I want to just use the photo that's already in the database. And not update the image field at all. But in my code whenever I am trying to without uploading new image form is not taking the old input value.
Here is my edit function:
public function expenseupdate1(){
$input = Input::only('id','Expense_date','Expense_category_id','Vendor_id','Customer_id','Amount','Tax1_id','Tax2_id','Note','Receipt');
$data=new Expense;
$id=$input['id'];
$Expense_date=$input['Expense_date'];
$Expense_category_id=$input['Expense_category_id'];
$Vendor_id=$input['Vendor_id'];
$Customer_id=$input['Customer_id'];
$Amount=$input['Amount'];
$Tax1_id=$input['Tax1_id'];
$Tax2_id=$input['Tax2_id'];
$Note=$input['Note'];
if(Input::hasFile('Receipt')) {
$file = Input::file('Receipt');
$name = time() . '-' . $file->getClientOriginalName();
$data->Receipt = $name;
$file->move(public_path() . '/images/', $name);
}
$affectedrows=Expense::where('id', '=', $id)->update(array('Expense_date' => $Expense_date,'Expense_category_id'=>$Expense_category_id,'Vendor_id'=>$Vendor_id,'Customer_id'=>$Customer_id,'Amount'=>$Amount,'Tax1_id'=>$Tax1_id,'Tax2_id'=>$Tax2_id,'Note'=>$Note,'Receipt'=>$Receipt));
return redirect('expenseinfo');
}
and here is my update form image field code:
<td> <div class="form-group"style="margin-left:-305px">
{!! Form::label('image', 'Receipt') !!}
<input Input::old('Receipt'), type="file" name="Receipt" value = '{{$data->Receipt}}'></td><td><?php echo $data->Receipt; ?></td>
</div></td>
<tr>
<td>{!! Form::submit('Update', array( 'class'=>'' )) !!}
{!! Form::close() !!}</td>
Any help would be appreciated greatly
You wouldn't set a default value for file.
The file input type creates a field
through which users can upload files
from their local computer or network.
The VALUE attribute specifies the name
of the initial file, but it is
typically ignored by browsers as a
security precaution.
So, your application is behaving correctly. Since the image is already in the database you wouldn't need to uploaded it again.
Also, just FYI but you can clean up your controller method dramatically!
/**
* Update Expense 1
*
* #param Request $request
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function expenseupdate1(Request $request){
$expense = Expense::find($request->input('id'));
$expense->fill($request->only('id','Expense_date','Expense_category_id','Vendor_id','Customer_id','Amount','Tax1_id','Tax2_id','Note','Receipt'));
if($request->hasFile('Receipt')) {
$file = $request->file('Receipt');
$name = time() . '-' . $file->getClientOriginalName();
$expense->Receipt = $name;
$file->move(public_path('/images/'), $name);
}
$expense->save();
return redirect('expenseinfo');
}
The above assumes you have the necessary use statements at the top of you're controller i.e.
use Illuminate\Http\Request;
use App\Expense; //Assuming that Expense is in this namespace
If you haven't already, you should set the fillable array for you model to allow the fill() method (mass assignment) to work http://laravel.com/docs/5.1/eloquent#mass-assignment
There is even more you can do but I have already gone outside the scope of this question. I would, however, suggest looking at:
http://laravel.com/docs/5.1/routing#route-model-binding
http://laravel.com/docs/5.1/controllers#restful-resource-controllers
http://laravel.com/docs/5.1/controllers#dependency-injection-and-controllers
Hope this helps!

Why data is not send by form submitting (zf2 forms + filters)?

I have problem:
When I fill in form and pressing add button page is reloaded, but no data is added to the database.
Code of NewsController, add action is below:
public function addAction() {
$form = new AddNewsForm();
$form->get('submit')->setValue('Add1');
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
var_dump($form->isValid());
if ($form->isValid()) {
echo "form is valid";
$objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$blogpost = new NewsItem();
$blogpost->exchangeArray($form->getData());
$blogpost->setCreated(time());
$blogpost->setUserId(0);
$objectManager->persist($blogpost);
$objectManager->flush();
// Redirect to list of blogposts
return $this->redirect()->toRoute('news');
}
}
return array('form' => $form);
}
Class AddNewsForm is included as use \News\Form\AddNewsForm as AddNewsForm; above.
I tried to debug my code and realized, that $form->isValid() return false all time. I tried to fill in all fields of form — it says that form is not valid. If not all fields are filled in it false too.
The problem is with validation, I think, so I will add here how I assing filter to the form. This is how I assing filter to my form:
$this->setInputFilter(new AddNewsInputFilter());
Class AddNewsInputFilter is included by this:
use \News\Form\AddNewsInputFilter as AddNewsInputFilter;
I don't think it is good to paste there ~100 lines of code, so I will just give a link to files in my github repo (full code of controllers/files available here):
AddNewsForm.php — file, where I create the form
AddNewsInputFilter.php — file, where I set fil
NewsController.php — file, controller, where I call created form
Repository link — root dir of my module
So the problem is that $form->isValid(); doesn't show is form valid or not properly and I don't know why. Note, that request is getting properly and first condition is passed (but second is not passed). It is the problem, thats why I am writing here.
How I can solve it?
Thanks is advance!
try var_dump($form->getMessages()) and var_dump($form->getInputFilter()->getMessages()) in controller(after calling $form->isValid()) or in view . see what error you getting and on witch element ?
NOTICE : getMessages() will be empty if $form->isValid() has not been called yet,
UPDATE : do this in controller :
var_dump($form->isValid());
var_dump($form->getMessages())
var_dump($form->getInputFilter()->getMessages())

How do I query complex data and return the data in the correct objects in Zend Framework 2?

I'm just starting out with ZF2 and I've run into a stumbling block and I cant find any useful advice on the internet.
Setting up retrieval of data from a single table and injecting it directly into a specific model is easy, for example, pulling data from a single row from 'school' table and injecting to a 'school' model.
However, I have some slightly more complex data and can't figure out how to return the data in the form of the correct model. For example, pulling multiple addresses from a school address table with a join on the school table.
I've got the following method in my AddressTable object...
public function fetchAllSchoolAddresses($school_id)
{
$stmt = $this->adapter->createStatement();
$stmt->prepare("CALL get_school_addresses(3)");
$stmt->getResource()->bindParam(3, $school_id, \PDO::PARAM_INT, 3);
$resultSet = $stmt->execute();
$addresses = new \ArrayObject();
if(!empty($resultSet)){
foreach ($resultSet as $result) {
$addresses->append($result);
}
}
return $addresses;
}
This quite nicely returns an array of addresses data but I want these results to be returned as Address objects. I'm not sure how to do this?
ZF2 comes with some standard Hydrators, which you can extend / modify if you wish.
http://framework.zend.com/manual/2.0/en/modules/zend.stdlib.hydrator.html
You could create a Hydrator for your School Object, and a Hydrator for your Address object.
The hydrators will build the object for you given the array data from the database for example
For example, you would Hydrate your School Object, and then find all addresses (like above) and use another hydrator to hydrate those. You would then add those to the School object to get your object graph as needed
$school->addAddress($address); // etc
Have a look here to see an example of using Hydrators and Hydrating ResultSets:
http://blog.evan.pro/zf2-tablegateway-hydration
http://framework.zend.com/manual/2.0/en/modules/zend.db.result-set.html
for exampple you could do something like this:
// How ever you want to get your database result do it here..
// this is where you get all addresses for your School
$stmt = $driver->createStatement($sql);
$stmt->prepare($parameters);
$result = $stmt->execute();
$resultSet = new HydratingResultSet(new ReflectionHydrator, new SchoolAddress);
$resultSet->initialize($result);
foreach ($resultSet as $address) {
$school->addAddress($address);
echo $address->getCity() . ' ' . $user->getPostcode() . PHP_EOL;
}
You would have a resultset (collection) of Addresses to add to your School.
That's code is just a very rough example hacked from the code in the docs to give an idea of what you do
How about this?
if(!empty($resultSet)){
foreach ($resultSet as $result) {
$address = new Address();
$address->exchangeArray($result);
$addresses->append($address);
}
}

Additional criteria to symfony filter

i'm working on a symfony project to manage a database. First i explain how it works:
In the database, all elements are associated to an unique element 'scene'. When a user accesses the application, chooses what scene he wants to see (it saves that in a user parameter). So when listing elements, the application should only list elements associated with the scene selected by the user.
*Note: all elements have an scene attribute in the table definition.
So my problem comes here:
I developed a listing of an element entities using the help of a sfPropelPager class to paginate. Also added some filters to search in the list, and for that i used the filter system provided by symfony (<element>FormFilter.class.php and stuff).
Now i want the list to not show elements from other scenes than the selected by the user.
How can i do to add additional criteria to the criteria given by the filter class?
or How would you solve the problem?
here is my action code:
public function executeUnidadfilter(sfWebRequest $request){
$this->filter = new BaUnidadorganizativaTblFormFilter();
$c = $this->filter->getCriteria();
$this->filter->bind($request->getParameter($this->filter->getName()));
if($this->filter->isValid()){
$this->pager = new sfPropelPager('BaUnidadorganizativaTbl',$this->sfPropelPagerLines);
echo $this->getUser()->getEscenario();
$this->pager->setCriteria($c);
$this->pager->init();
}else{
$this->pager = new sfPropelPager('BaUnidadorganizativaTbl',$this->sfPropelPagerLines);
$this->pager->init();
}
$this->setTemplate('Unidadlist');
}
*Note: 'scene' mentioned below is Escenario in the code
thank you very much for your time
I solved the problem. The trouble was that i assigned the formfilter generated criteria to my criteria var Before the filter was filled. That's why of the error.
The resulting code is that:
public function executeUnidadfilter(sfWebRequest $request){
$this->filter = new BaUnidadorganizativaTblFormFilter();
$this->filter->bind($request->getParameter($this->filter->getName()));
if($this->filter->isValid()){
$this->pager = new sfPropelPager('BaUnidadorganizativaTbl',$this->sfPropelPagerLines);
$esc = $this->getUser()->getEscenario();
$c = new Criteria();
$c = $this->filter->getCriteria();
$c->addAnd('codigo_escenario',$esc);
$this->pager->setCriteria($c);
$this->pager->init();
}else{
$this->pager = new sfPropelPager('BaUnidadorganizativaTbl',$this->sfPropelPagerLines);
$this->pager->setCriteria($this->filter->getCriteria());
$this->pager->init();
}
$this->message=null;
$this->messageType=null;
$this->setTemplate('Unidadlist');
}

How to display extra fields in article with K2

currently I've got Jreviews installed and I'd like to replace it by K2 to list specialized shops with addresses, phones, maps, opening hours ...
With K2 I guess I'll need to define extra custom fields to hold those specific information. No problem.
But, how may I configure things to have those fields displayed in the detailed article/items for a specific shop ?
Many thanks,
Tibi.
// In the item template you can skip this first line...
$this->item->extra_fields = K2ModelItem::getItemExtraFields($this->item->extra_fields);
$extraFlds = array();
if ( $this->item->extra_fields ){
foreach ( $this->item->extra_fields as $key=>$extraField ){
$extraFlds[ $extraField->name ] = $extraField->value;
}
}
Then you can access your extra fields in the associate array like $extraFlds['my field']
After a lot of tries here what i used and worked for me
<?php
// if form is empty show default form
$k2obj = new K2ModelItem();
$fields = $k2obj->getItemExtraFields($this->item->extra_fields, $this->item);
//echo $this->item->extraFields->State->name;
echo $this->item->extraFields->FIELD_ALIAS->value;
?>
This is working and noted its all pegged to instantiating the class.
Note: I am using this in the k2 item i version 2.6.7 Joomla 2.5.14
if you want show custum field in k2 table list go to:
components\com_k2\templates\default\category_item.php
and edit file near line 136 like this:
<?php foreach ($this->item->extra_fields as $key=>$extraField):
**if(strpos($extraField->name,"/")){**
?>
<li class="<?php echo ($key%2) ? "odd" : "even"; ?> type<?php echo ucfirst($extraField->type); ?> group<?php echo $extraField->group; ?>">
<span class="catItemExtraFieldsLabel"><?php echo $extraField->name; ?></span>
<span class="catItemExtraFieldsValue"><?php echo $extraField->value; ?></span>
</li>
<?php **}** endforeach; ?>
i do that in my site: www.joomir.com
The problem is that $this->item->extra_fields is actually a JSON string retrieved from the database, so you have to decode it first. It's structure is rather complicated (and unfortunately each field is labelled by it's id, it's name doesn't appear at all), you'll see it if you execute:
print_r($this->item->extra_fields);`
If you want to call field values by it's field name I'd do it like this:
if ($this->item->params->get('itemExtraFields')) {
$item_extra_fields = json_decode($this->item->extra_fields);
$put_your_extra_field1_name_here = $item_extra_fields[1]->value;
$put_your_extra_field2_name_here = $item_extra_fields[2]->value;
$put_your_extra_field3_name_here = $item_extra_fields[3]->value;
$put_your_extra_field4_name_here = $item_extra_fields[4]->value;
}
Notice that this is useful if the extra field you need is text, but it can be an array or whatever so you might have to code a little bit more. Hope this is useful!
In K2 you set the parameters for how an item displays at the category level. There is an option to display the extra fields in both Item view options in category listings as well as the Item view options.
By default, the built in K2 template will display the extra fields under a heading "Additional Information" with an unordered list of field name and values. You can override that template and make the extra fields display any way you like.

Resources