I'm trying to submit updates to items in the Items model. However, Ardent never actually performs the updates when the update method receives them but doesn't throw an error:
public function update($id)
{
$item = Item::findOrFail($id);
if ($item->save()) {
return Redirect::back()->with('message', "Item #$id updated!");
} else {
return Redirect::back()->withInput()->withErrors($item->errors());
}
}
What is wrong with my controller logic here?
It looks like you need to set those variables
class Item extends \LaravelBook\Ardent\Ardent {
// hydrates on new entries' validation
public $autoHydrateEntityFromInput = true;
// hydrates whenever validation is called
public $forceEntityHydrationFromInput = true;
}
properly to get the behavior you expect.
Source: https://github.com/laravelbook/ardent#automatically-hydrate-ardent-entities
Related
I have a component where I display the list of transactions and show details of each transaction using a modal.
class TableTranscation extends Component
{
use WithPagination, Alert, AuthorizesRequests;
...
public $transaction;
public $detailModal = false;
public function showDetail($id)
{
$this->transaction = Transaction::find($id);
$this->detailModal = true;
//dd transaction variable here return correct result
//dd($this->transaction);
}
public function render()
{
return view("livewire.user.transaction.transaction-table", [
"transactions" => current_user()->transactions()->paginate($this->perPage)
]);
}
}
Whenever I call to showDetail method from the component, the transaction remains Array[0] in Livewire devtool.
I tried adding the mount method but the Livewire devtool also showed Array[0].
public function mount()
{
$this->transaction = Transaction::find(1);
}
When I {{ dd($transaction) }} from the view it return correct transaction.
Any solution to this problem or bug from the tool?
I have a Blade Component class like this:
class RolesSelect extends Component
{
public $roles;
public $user;
public function __construct($roles = null, $user = null)
{
//... some logic goes here (irrelevant)
}
public function isSelected($user,$role)
{
// ... some logic
}
public function render()
{
return view('components.roles-select');
}
}
When I render my component as usual <x-roles-select></x-roles-select> everything goest fine.
But here starts the problem: when I load the component via AJAX, I use the view('components.roles-select')->render(). And the component can't see the isSelected method anymore.
It throws this error: Undefined variable: isSelected
I tried to research the Blade and Component classes, but only came this far:
$roleSelect = new RolesSelect($roles, $user);
$roleSelect->resolveView()->render();
I can access everything, but the isSelected method.
I was close enough. Dabbled a bit with the code, and got it working!
In my controller (or just the route method), you have to initialise the component class, and pass it's data to the view like this:
$roleSelect = new RolesSelect($roles, $user);
if (request()->wantsJson()) {
return response()->json([
'content' => $roleSelect->resolveView()->with($roleSelect->data())->render()
],200);
}
I have a model and I want to take an old the value of that model's field after save, I was using getOldAttribute() method and it always returns the latest value?
Code sample
class User extends ActiveRecord
{
public function fields()
{
return [
'id',
'name',
'email' //old value: example#example.com
];
}
}
class UserService extends BaseService
{
/**
* Current user have email is `test#test.com`
*/
public function update(User $user)
{
//before save
$oldEmailBeforSave = $user->getOldAttribute('email'); //work fine and value is `example#example.com`
//handle update user
$this->saveEntity($user)
//after save
$oldEmailAfterSave = $user->getOldAttribute('email'); //not work and value is `test#test.com`
}
}
According to the docs you can use the second parameter of the afterSave( $insert, $changedAttributes) which holds the old values of the attributes that were changed and were saved.
Your code should look like below if you want to get the email fields old value if it was changed
public function afterSave( $insert, $changedAttributes ){
parent::afterSave();
if(!$insert){
$oldEmail = $changedAttributes['email'];
//do something here with the old email value
}
}
When you save new attribute, it is no longer "old". getOldAttribute() represents state from database and allows you to compare whether and how attribute was changed between find() and save(). After calling save(), old attributes are refreshed, so getOldAttribute() will return the same as getAttribute().
If you want to access old state of object, you need to clone it and use these methods on clone - $cloned will represent state of object before calling save():
public function update(User $user)
{
//before save
$oldEmailBeforSave = $user->getOldAttribute('email'); // `example#example.com`
$cloned = clone $user;
//handle update user
$this->saveEntity($user)
//after save
$oldEmailAfterSave = $user->getOldAttribute('email'); // `test#test.com`
$oldEmailAfterSave = $cloned->getOldAttribute('email'); // `example#example.com`
}
I have a Form where I have to perform a validation after the basic form validation (extending/overriding the Form#isValid(...)). If this "post-validation validation" fails, I add an error message to the Form like this:
MyForm extends Form
{
protected $errorMessages = [];
public function isValid()
{
$isValidBasic = parent::isValid();
$isValidAdditional = ...;
if (! $isValidAdditional) {
$this->addErrorMessage('my custom error message');
}
return $isValidBasic && $isValidAdditional;
}
public function addErrorMessage($message)
{
$this->errorMessages[] = $message;
return $this;
}
public function getErrorMessages()
{
return $this->errorMessages;
}
public function getMessages($elementName = null)
{
if ($elementName) {
$messages = parent::getMessages($elementName);
} else {
$messages = array_merge($this->getErrorMessages(), parent::getMessages($elementName));
}
return $messages;
}
}
It works, but "my custom error message" is ignored by the "translator" and I also get the original error message displayed.
I've already add a new translation file
class Application\Module
namespace Application;
...
class Module
{
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$translator = $e->getApplication()
->getServiceManager()
->get('translator');
$translator->addTranslationFile('phpArray',
'./vendor/zendframework/zend-i18n-resources/languages/de/Zend_Validate.php');
$translator->addTranslationFile('phpArray',
'./vendor/my/lib/src/i18n-resources/languages/de/Validate.php');
AbstractValidator::setDefaultTranslator($translator);
}
}
... and it also works. But in this case it doesn't.
How to get custom Form error messages translated in ZF2?
On my ZF2 website, I solved it adding the following method in my models and forms:
protected function _translate($msg)
{
return $msg;
}
Don't ask me why it's working, but it works with only this, the error messages are translated.
I've used setNotification method of model by initial data from Controller within a variable $data as array. I have used self:: in this method instead of used table or Notification::save() or $obj->save(). by this way I don't know how to get Id which the last id after insert was done in laravel because I used $this->attributes that it is the protected variable in Model.
class Notification extends Model
{
protected $table = 'notification';
public $timestamps = true;
private $_data = false;
public function setNotification($data)
{
if (is_array($data)) {
$this->attributes = $data;
self::save();
}
}
}
Try something like $this->attributes[id] after save() is executed.
I suggest You to use create method instead and return created object, so then You can access id property.
public function setNotification($data)
{
if (is_array($data)) {
return $this->create($data);
}
return null;
}