I'm using a custom datasource to consume webservice.
Create, Read and Update work well but Delete doesn't works.
Here is my code calling the delete method in my controller.
public function delete($id){
$this->autoRender = false;
debug($this->Article->delete($id));
}
And here the code in my datasource
public function delete(Model $Model, $id = null) {
echo "Display a message if this method is called";
$json = $this->Http->post(CakeSession::read('Site.url') . '/webservice/delete/', array(
'id' => $id,
'apiKey' => $this->config['apiKey'],
'model' => $Model->name
));
$res = json_decode($json, true);
if (is_null($res)) {
$error = json_last_error();
throw new CakeException($error);
}
return true;
}
But when I want to delete an item, the debug(); display false.
I have no other displays.
I don't understand why my delete method isn't called correctly.
Is there something wrong in my code ?
Thanks
Let's check: you're only passing a parameter to your method:
$this->Article->delete($id)
According to the method that you created, the first parameter, which is required, is the Model. The second is $id:
public function delete(Model $Model, $id = null)
During the method you want to use both parameters. Here:
'id' => $id
And here:
'model' => $Model->name
Based on this, you need to review how this method will be called. BTW, if you want override delete() method, according the book, you need something like this: delete(int $id = null, boolean $cascade = true).
Related
I'm using voyager admin panel. I want to check the attributes that are changed when I submit the form. I'm using isDirty() & getDirty() but that is not working.
It is showing that the error
Method Illuminate\Http\Request::isDirty does not exist.
Sometimes showing this error.
Call to a member function isDirty() on string
update Controller
public function update(Request $request, $id)
{
$slug = $this->getSlug($request);
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first();
// Compatibility with Model binding.
$id = $id instanceof \Illuminate\Database\Eloquent\Model
? $id->{$id->getKeyName()}
: $id;
$model = app($dataType->model_name);
$query = $model->query();
$data = $query->findOrFail($id);
$this->insertUpdateData($request, $slug, $dataType->editRows, $data);
// That part is showing an error
dd($request->isDirty(['status']));
return $redirect->with([
'message' => __('voyager::generic.successfully_updated')." {$dataType->getTranslatedAttribute('display_name_singular')}",
'alert-type' => 'success',
]);
}
Request will not show the results it will work only with the model. So I used $data instead of $request. And I've to show it in an array. Something like this.
$data = $query->findOrFail($id);
$data->status = $request->status;
dd($data->isDirty('status'));
I works on my side.
Using Laravel Spark, if I wanted to swap in a new implementation for the configureTeamForNewUser, at first it looks like it's possible because of the Spark::interact call here
#File: spark/src/Interactions/Auth/Register.php
Spark::interact(self::class.'#configureTeamForNewUser', [$request, $user]);
i.e. the framework calls configureTeamForNewUser using Spark::interact, which means I can Spark::swap it.
However, if I look at the configureTemForNewUser method itself
#File: spark/src/Interactions/Auth/Register.php
public function configureTeamForNewUser(RegisterRequest $request, $user)
{
if ($invitation = $request->invitation()) {
Spark::interact(AddTeamMember::class, [$invitation->team, $user]);
self::$team = $invitation->team;
$invitation->delete();
} elseif (Spark::onlyTeamPlans()) {
self::$team = Spark::interact(CreateTeam::class, [
$user, ['name' => $request->team, 'slug' => $request->team_slug]
]);
}
$user->currentTeam();
}
This method assigns a value to the private $team class property. It's my understanding that if I use Spark::swap my callback is called instead of the original method. Initial tests confirm this. However, since my callback can't set $team, this means my callback would change the behavior of the system in a way that's going to break other spark functionality.
Is the above a correct understanding of the system? Or am I missing something, and it would be possible to swap in another function call (somehow calling the original configureTeamForNewUser)?
Of course, you can swap this configureTeamForNewUser method. Spark create a team for a user at the registration. You have to add the swap method inside the Booted() method of App/Providers/SparkServiceProvider.php class.
in the top use following,
use Laravel\Spark\Contracts\Interactions\Auth\Register;
use Laravel\Spark\Contracts\Http\Requests\Auth\RegisterRequest;
use Laravel\Spark\Contracts\Interactions\Settings\Teams\CreateTeam;
use Laravel\Spark\Contracts\Interactions\Settings\Teams\AddTeamMember;
In my case I want to add new field call "custom_one" to the teams table. Inside the booted() method, swap the method as bellow.
Spark::swap('Register#configureTeamForNewUser', function(RegisterRequest $request, $user){
if ($invitation = $request->invitation()) {
Spark::interact(AddTeamMember::class, [$invitation->team, $user]);
self::$team = $invitation->team;
$invitation->delete();
} elseif (Spark::onlyTeamPlans()) {
self::$team = Spark::interact(CreateTeam::class, [ $user,
[
'name' => $request->team,
'slug' => $request->team_slug,
'custom_one' => $request->custom_one,
] ]);
}
$user->currentTeam();
});
In order to add a new custom_one field, I had to swap the TeamRepository#createmethod as well. After swapping configureTeamForNewUser method, swap the TeamRepository#create method onside the booted(),
Spark::swap('TeamRepository#create', function ($user, $data) {
$attributes = [
'owner_id' => $user->id,
'name' => $data['name'],
'custom_one' => $data['custom_one'],
'trial_ends_at' => Carbon::now()->addDays(Spark::teamTrialDays()),
];
if (Spark::teamsIdentifiedByPath()) {
$attributes['slug'] = $data['slug'];
}
return Spark::team()->forceCreate($attributes);
});
Then proceed with your registration.
See Laravel Spark documentation
I have one temporary model as viewModel. In my CRUD actions (for example actionCreate) I want to get this viewModel data and assign that to a ActiveRecord model. I used below code but my model object atrribute always show NULL value for attributes:
$model = new _Users();
if ($model->load(Yii::$app->request->post())) {
Yii::info($model->attributes,'test'); // NULL
$attributesValue =[
'title' => $_POST['_Users']['title'],
'type' => $_POST['_Users']['type'],
];
$model->attributes = $attributesValue;
Yii::info($model->attributes,'test'); // NULL
$dbModel = new Users();
$dbModel->title = $model->title;
$dbModel->type = $model->type . ' CYC'; // CYC is static type code
Yii::info($dbModel->attributes,'test'); // NULL
if ($dbModel->save()) {
return $this->redirect(['view', 'id' => $dbModel->id]); // Page redirect to blank page
}
}
else {
return $this->render('create', [
'model' => $model,
]);
}
I think $model->load(Yii::$app->request->post()) not working and object attribute being NULL. Is it Yii2 bug or my code is incorrect??
If there is no rule for your attribute the $model->load() will ignore those not in the rules of the model.
Add your attributes to the rules function
public function rules()
{
return [
...
[['attribute_name'], 'type'],
...
];
}
To fetch data for an individually attributes(db-fields) in yii2.0 then you should just do as:
echo $yourModel->getAttribute('email');
ActiveRecord $attributes is a private property
Use $model->getAttribute(string)
You can use following codes:
$model = new _Users();
$model->attributes=Yii::$app->request->post('_Users');
$model->title= $model->title
$model->type = $model->type . ' CYC'; // CYC is static type code
#$model->sampleAttribute='Hello World';
Declare attribute as private then
echo $yourModel->attribute
work as expected
You must remove all public properties (title, type, etc.) in your _User model and $model->attributes = $post will work correctly.
I have also encountered the same problem, i Add my attributes to the rules function,but also error. And i found the reason for this problem. It is beause that the submit form's name in corresponding view file is not the same as the model's name which you use in controller
[controller file]:
$model=new SearchForm();
[view file]:
<input name="SearchForm[attribus]" ...
or
[view file]:
<?= $form->field($model,'atrribus')->textInput()?>
My code is fairly complex so I will try to explain in the simplest way possible
I have a parent entity ValueList. This 'list' has many ValueListItems.
class ValueList
{
//...
/**
* #ODM\ReferenceMany(
* targetDocument="JobboardBase\Entity\ValueListItem",
* sort={"order"="asc"},
* cascade={"all"}
* )
*/
protected $items;
}
I then have a service method that adds a new ValueListItem to this (already managed) ValueList.
public function createValueListItem(ValueListItem $item, ValueList $list)
{
try {
$om = $this->getObjectManager();
$om->persist($item);
$list->addItem($item);
$om->persist($list);
$om->flush();
return $item;
} catch (\Exception $e) {
throw $e;
}
}
This adds the entity correctly to the Mongo collection. However because I am executing the controller action with an AJAX call I also need to re-dispatch the 'indexAction' to return a the updated 'list' HTML asynchronously.
// ListItemController::createAndAttachValueItemToParentListAction()
// ....
// Below is the successful 'add' of the above method call return
if ($service->createValueListItem($form->getData(), $list)) {
$content = $this->forward()->dispatch('JobboardBase\Controller\ListItem', array(
'action' => 'index',
'id' => $list->getId()
));
return $this->jsonModel(array(
'success' => true,
'messages' => array($message),
'content' => $content
));
//... IndexAction
public function indexAction() {
// ...
$items = $list->getItems(); // Returns 0 (when there should be 1)
//...
}
The HTML returned via the forward() call (in $content) doesn't include the new added ValueListItem entity. It will however display correctly when I refresh the page.
Doctrine seems to be returning a cached ValueList entity that doesn't include the newly added ValueListItem - Only when a new requested is made does the new item get displayed.
My question is why is doctrine returning the 'old' entity rather than the updated entity? I was under the impression that it should be the same instance and therefore updated by reference?
you can refresh your model with the actual data using entity manager refresh method:
$om->refresh($list);
Yii-jedis!
I'm working on some old Yii-project and must to add to them some features. Yii is quite logical framework but it has some things I couldn't understand. Perhaps I haven't understand Yii-way yet. So I'll describe my problem step-by-step. For impatients - briefly question at the end.
Intro: I want to add human-readable URLs to my project.
Now URLs looks like: www.site.com/article/359
And I want them to look like this: www.site.com/article/how-to-make-pretty-urls
Very important: old articles must be available on old format URLs, and new - on new URLs.
Step 1: First, I've updated rewrite rules in config/main.php:
'<controller:\w+>/<id:\S+>' => '<controller>/view',
And I've added new texturl column to article table. So we will store here human-readable-part-of-url for new articles. Then I've updated one article with texturl for tests.
Step 2: Application show articles in actionView of ArticleController so I've added there this code for preproccessing ID parameter:
if (is_numeric($id)) {
// User try to get /article/359
$model = $this->loadModel($id); // Article::model()->findByPk($id);
if ($model->text_url !== null) {
// If article with ID=359 have text url -> redirect to /article/text-url
$this->redirect(array('view', 'id' => $model->text_url), true, 301);
}
} else {
// User try to get /article/text-url
$model = Article::model()->findByAttributes(array('text_url' => $id));
$id = ($model !== null) ? $model->id : null ;
}
And then begin legacy code:
$model = $this->loadModel($id); // Load article by numeric ID
// etc
It works perfectly! But...
Step 3: But we have many actions with ID parameter! What we have to do? Update all actions with that code? I think it's ugly. I've found CController::beforeAction method. Looks good! So I declare beforeAction and place ID preproccessing there:
protected function beforeAction($action) {
$actionToRun = $action->getId();
$id = Yii::app()->getRequest()->getQuery('id');
if (is_numeric($id)) {
$model = $this->loadModel($id);
if ($model->text_url !== null) {
$this->redirect(array('view', 'id' => $model->text_url), true, 301);
}
} else {
$model = Article::model()->findByAttributes(array('text_url' => $id));
$id = ($model !== null) ? $model->id : null ;
}
return parent::beforeAction($action->runWithParams(array('id' => $id)));
}
Yes, it works with both URL-formats, but it executes actionView TWICE and shows page two times! What can I do with this? I've totally confused. Have I choose a right way to solve my problem?
Briefly: Can I proceess ID (GET-parameter) before execute of any actions and then run requested action (once!) with modified only ID parameter?
Last line should be:
return parent::beforeAction($action);
Also to ask you i didnt get your step:3.
As you said you have many controller and you don't need to write code in each file, so you are using beforeAction:
But you have only text_url related to article for all controllers??
$model = Article::model()->findByAttributes(array('text_url' => $id));
===== updated answer ======
I have changed this function, check now.
If $id is not nummeric then we will find it's id using model and set $_GET['id'], so in further controller it will use that numberic id.
protected function beforeAction($action) {
$id = Yii::app()->getRequest()->getQuery('id');
if(!is_numeric($id)) // $id = how-to-make-pretty-urls
{
$model = Article::model()->findByAttributes(array('text_url' => $id));
$_GET['id'] = $model->id ;
}
return parent::beforeAction($action);
}
Sorry, I haven't read it all carefully but have you considered using this extension?