How to use model attribute value in behavior config Yii - php

I want create ImageBehavior for uploading and saving images. My behavior have two fields: imagePath and imageField. In my model i'm wrote:
public function behaviors(){
return array(
'imageBehavior' => array(
'class' => 'ImageBehavior',
'imagePath' => 'images/avatar-pics/'.$this->user->username,
'imageField' => 'avatar',
),
);
}
but this doesn't worked - i receive path -
images/avatar-pics//image.png
What a solution? Create in behavior field imageFolder and add to config 'imageFolder' => 'user->username'? Thanks.

As a suggestion:
Change the way you use your behavior and add some codes to your models. Take a look at the following example:
For example, your behavior:
class ImageBehavior extends CBehavior {
public $imagePath;
public $imageField;
public function getImagePath() {
return $this->imagePath;
}
}
Your model:
class TestModel extends CFormModel {
private $imagePath = '/home/x/y';
public function setImagePath($imagePath) {
$this->imagePath = $imagePath;
$this->attachBehaviors(array(
array(
'class' => 'ImageBehavior',
'imagePath' => $this->imagePath
)
));
}
public function init() {
$this->setImagePath($this->imagePath);
parent::init();
}
}
Now, take a look at tests and results:
$model=new TestModel();
CVarDumper::dump($model->getImagePath()); //output: /home/x/y
$model->setImagePath('/home/x/path2');
CVarDumper::dump($model->getImagePath()); //output: /home/x/path2
$model->setImagePath('/home/x/path3');
CVarDumper::dump($model->getImagePath()); //output: /home/x/path3
By this way, if you do not set any imagePath it uses model's default value. In front, each time you change the imagePath your path will change in your behavior.
Note: This is just a suggestion. By this, you can customize your setImagePath method to get the value from everywhere you want(another model, session and so on...).

Sorry for answering own question, but almost two years later build correct vision to this issue:
1) don't use line
'images/avatar-pics/'.$this->user->username
in your behavoir - it throws a notice "Trying to get property of non-object" - good application doesn't thows notices and warnings.
2) all you need is use
'images/avatar-pics/' . CHtml::value($this, 'user.username')
instead. If $this->user is null, value method returns null, so be sure that you have related user to your model.

//inside the behavior:
$this->owner->user->username;
$this->owner - it's your model. Behavior is initialized before filling attributes, and the attribute value can be get only after the initialization.

Related

Laravel 6 : Duplicate database entry on polymorphisme relation save

I try to save a morph relationship in my database, but when i try to save it I Have tow entry in every table use for the relation.
here is my client class
class Client extends Model
{
protected $guarded = [];
public function clientelle(){
return $this->morphTo();
}
}
my particulier class
class Particulier extends Model
{
protected $guarded = [];
public function client(){
return $this->morphOne(Client::class,'clientelle');
}
}
So when I try to save like that :
$particulier = new Particulier();
$particulier->nom = $request->nom;
$particulier->prenom = $request->prenom;
$particulier->save();
$particulier->client()->create(['telephone'=>$request->telephone,'adresse'=>$request->adresse,'email'=>$request->email]);
My database save two same recorde. Here is my problem.
So I have try diffrente thing to avoid it but I have error every time
delete $particulier->save(); but SQL error id don't exist
replace create([...]) by save([...]) or sync([...]) but don't work
Thank you in advance
So I have finally find a worst solution...
In your controller add int var and init it to 0 like that :
Private $checkDouble=0;
In place where you want save your relation create if block and put in all of your model save like that :
if($this->checkDouble==0) {
$this->checkDouble = $this->checkDouble + 1; //Increase your var value
$particulier = Particulier::create(['nom' => $request->nom, 'prenom' => $request->prenom]);
$particulier->client()->create(['telephone' => $request->telephone, 'adresse' => $request->adresse, 'email' => $request->email]);
}
And no more duplicate data
I know is really worst solution but I don't see any best solution ^^

Laravel - Polymorphic relationship not working

So I have the following code:
class PageSection extends Model {
protected $table = "PageSection";
const TYPE_CURATED = 0;
const TYPE_AUTOMATED = 1;
public function list() {
return $this->morphTo('list', 'entity_type', 'id_Entity');
}
}
then in AppServiceProvider.php I have the following:
use App\PageSection;
use App\PageSectionGroup;
use App\PageListEntry;
use App\RSSFeed;
use App\Shortcut;
use App\RSSEpisode;
use App\PageList;
use App\AutomatedList;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
Relation::morphMap([
'Section' => PageSection::class,
'SectionGroup' => PageSectionGroup::class,
PageSection::TYPE_CURATED => PageList::class,
PageSection::TYPE_AUTOMATED => AutomatedList::class,
PageListEntry::TYPE_FEED => RSSFeed::class,
PageListEntry::TYPE_SHORTCUT => Shortcut::class,
PageListEntry::TYPE_EPISODE => RSSEpisode::class
]);
}
Then I have a test route in my api routes that checks to see if the list is being loaded, and it returns null: (Yes, I've verified that the section itself exists)
Route::get('/test', function() {
$section = PageSection::with(['list', 'type'])->find(1);
// this returns null
return $section->list;
});
My database schema for PageSection is such that entity_type tells what the model is, and id_Entity is the foreign key for that model, which is named 'id' on the referenced table.
The other relations defined in morphMap are working properly, yet for some reason the list() relationship in PageSection is not. I'm not sure what I'm doing wrong here.. any help would be appreciated.
Ok, so I figured out what was going on. It's probably a bug with Laravel's morphMap. I was using 0 for the PageSection::TYPE_CURATED constant, which is a falsey value. When I switched to:
Relation::morphMap([
'PageList' => PageList::class,
'AutomatedList' => AutomatedList::class,
'Section' => PageSection::class,
'SectionGroup' => PageSectionGroup::class,
PageListEntry::TYPE_FEED => RSSFeed::class,
PageListEntry::TYPE_SHORTCUT => Shortcut::class,
PageListEntry::TYPE_EPISODE => RSSEpisode::class
]);
it all worked fine. Seems like Laravel doesn't like the value 0.

How can I get the list of required parameters of a yii 2.0 action as an array?

When a user visits a particular url in my yii 2.0 application without required parameters, I want to present a form to collect the required missing parameters.
for this purpose, I need the names of missing parameters, e.g. I have a function
public function actionBlast ($bomb, $building) {
}
I expect the results as an array like this
$args = [0=>'bomb', 1=>'building'];
I tried func_get_args() but it returns null, and the undocumented ReflectionFunctionAbstract::getParameters ( void ) etc. Any other way out?
I think the best way to achieve what you want is to override the default ErrorAction.
Inside your controllers directory, create:
controllers
actions
ErrorAction.php
In ErrorAction.php, add:
<?php
namespace frontend\controllers\actions;
use Yii;
use yii\web\ErrorAction as DefaultErrorAction;
class ErrorAction extends DefaultErrorAction
{
public function run()
{
$missing_msg = 'Missing required parameters:';
$exception = Yii::$app->getErrorHandler()->exception;
if (substr($exception->getMessage(), 0, strlen($missing_msg)) === $missing_msg) {
$parameters = explode(',', substr($exception->getMessage(), strlen($missing_msg)));
return $this->controller->render('missing_params_form' ?: $this->id, [
'parameters' => $parameters,
]);
}
return parent::run();
}
}
In your controller add:
public function actions()
{
return [
'error' => [
'class' => 'frontend\controllers\actions\ErrorAction',
],
];
}
and create a view "missing_params_form.php" in your controller `s view directory, where you can generate your form fields.
I believe this to be your best option, though you may need to update it in case a Yii update changes the error message.

Cakephp profile view looking for the wrong controller

I have a function that is used to edit a previously existing userprofile here is the controller
class PeoplesController extends AppController
{
public $name = "peoples";
public $helpers = array('Html', 'form', 'Js');
public $components = array('RequestHandler');
public function viewPerson($id = NULL) {
$this->set('person', $this->people->read(NULL, $id));
}
public function editPerson($id = NULL)
{
if(empty($this->data)) {
$this->data = $this->people->read(NULL, $id);
}
else {
if($this->people->save($this->data)) {
$this->Session-setFlash('The profile has been updated');
$this->redirect(array('action'=>'viewPerson', $id));
}
}
}
}
the view outputs a form prepopulated with the previous data
<h2>Edit Profile</h2>
<?php
echo $this->Form->create('people', array('action'=>'edit'));
echo $this->Form->input('firstName');
echo $this->Form->input('secondName');
echo $this->Form->input('addressOne');
echo $this->Form->input('addressTwo');
echo $this->Form->input('city');
echo $this->Form->input('county');
echo $this->Form->input('country');
echo $this->Form->input('postCode', array(
'label' => 'Zip Code',
));
echo $this->Form->input('dob', array(
'label' => 'Date of birth',
'dateFormat' => 'DMY',
'minYear' => date('Y') - 70,
'maxYear' => date('Y') - 18,
));
echo $this->Form->input('homePhone');
echo $this->Form->input('mobilePhone');
echo $this->Form->input('email', array(
'type' => 'email'
));
$goptions = array(1 => 'Male', 2 => 'Female');
$gattributes = array('legend' => false);
echo $this->Form->radio('gender',
$goptions, $gattributes
);
echo $this->Form->input('weight');
echo $this->Form->input('height');
echo $this->Form->input('referedBy');
echo $this->Form->input('id', array('type'=>'hidden'));
echo $this->Form->end('Edit Profile');
?>
the view seems to work fine #
http://localhost/Cake/peoples/editPerson/2
but when I hit submit the url changes to
http://localhost/Cake/people/edit/2
So I changed
echo $this->Form->create('people', array('action'=>'edit'));
to
echo $this->Form->create('people', array('action'=>'editPerson'));
and I tried changing the first parameter of the create function to peoples but as this refers to the model and not the controller it should be people so i changed it back
the error i get is
Error: PeopleController could not be found.
so it is looking for the wrong controller but I am not sure where that seeking for the controller takes place.
I did use to have the controller class name uncapitalised but I follwed some advice on the conventions and capitalised it but the other previous functions I had still work fine so I dont think that is the problem
any ideas why it is changing the url and looking for the wrong controller?
The form action is being set to the edit action
Irrespective of the current url - the form action is overridden to be an explicit action:
echo $this->Form->create(
'people',
array('action'=>'edit') // <-
);
This will force the url to point at the action edit, or /people/edit/<current id>.
To prevent that, just don't specify the action, and the form will submit to the current url:
echo $this->Form->create(
'people'
);
To specify the form action url
Use the url key, not the action key which only changes the action:
echo $this->Form->create(
'people',
array(
'url'=>'/submit/here/please/' // <- or specify as an array
)
);
Avoid/correct confusing names
The convention regarding model and controller names is that models are singular, and controllers are plural:
Model |  Controller
Singular Plural
Person People
In the question this isn't the case, The model is a plural, and the controller is a confusing plural-plural (Peoples can actually be used, but it means many groups of people)
Don't define properties needlessly
In the question, there's also this:
class PeoplesController extends AppController
{
public $name = "peoples";
At best that doesn't do anything, but since the name property is defined as lower case and cake expects it to be CamelCased - that's likely to cause inconsistent behavior.
Best to follow conventions and name the controller People, the model Person and don't specify a name at all.
Don't repeat yourself
And follow conventions for a much easier ride.
The function naming is duplicates the word "person"
instead of:
public function viewPerson($id = NULL) {
(so.. the code uses person, people and peoples ?)
it's advisable to use:
public function view($id = NULL) {
After all, in the people controller - what other kind of thing is there to view (if the answer is many things, that's another thing to address)?
This makes urls simple (/peoples/view/1, instead of /peoples/viewPeople/1) as well as making the code itself easier to read (PeoplesController::view instead of PeoplesController::viewPerson).
If you don't want to change the names of the action methods, making them lower cased and underscored will at least mean the urls are consistently cased, instead of /lower_case_controller/camelCasedAction/args.

How to Retrieve Image Files from Database Using Yii Framework?

Our Yii Framework application has the following defined as part of the UserProfileImages model:
public function getProfileImages($param, $user_id) {
if(isset($param['select']) && $param['select']=='all'){
$profile_images = UserProfileImages::model()->findAllByAttributes( array( 'user_id'=>$user_id) );
} else {
$profile_images = UserProfileImages::model()->findByAttributes( array( 'user_id'=>$user_id) );
}
return $profile_images;
}
How would I wire up the above snippet to a widget in my view to return all the images for a given user?
Bonus Question: Which image rotator do you suggest to render the above?
In your view file, add something like this, assuming that your controller specified $user_id:
$this->widget('UserProfileImagesWidget', array(
"userProfileImages" => UserProfileImages::getProfileImages(
array("select" => "all"),
$user_id
),
"user_id" => $user_id
));
Depending on your MVC philosophy, you could also retrieve the userProfileImages data in the controller and pass that data to your view.
Define a widget like this:
class UserProfileImagesWidget extends CWidget {
public $user_id;
public $userProfileImages = array();
public function run() {
$this->render("userProfileImage");
}
}
Finally, in the userProfileImages.php view file, you can do something like this:
if(!empty($this->userProfileImages)) {
// Your display magic
// You can access $this->user_id
}
As a side note: You might want to change the order of your parameters in getProfileImages. If $user_id is the first parameter, you can leave out $params completely in case you don't want to specify any.

Categories