Can't read named parameter in controller CakePHP - cakephp

I'm trying to pass a named parameter to a function. It actually is passed through before $this->request->is('post'), but debugKit placed after this line returns null. What gives?
Route:
http://localhost/bake/users/login/ref:post
Controller:
public function login() {
//it returns 'post' here successfully.
debug($this->params['named']['ref']);
if ($this->request->is('post')) {
//it returns 'null' here.
debug($this->params['named']['ref']);
}
}

I used sort of a pseudo method to go about it:
public function login() {
//set the value to the view.
$this->set('param', $this->params['named']['ref']);
if ($this->request->is('post')) {
$param = $this->request->data['param'];
}
}
In the view I added a hidden field:
<input type="hidden" name="data[param]" value="post"/>
So it gets the value with form is submitted.

If you're lazy:
$this->request->query('ref')
If you're curious:
Documentation here
Source code here

Related

Call Specific Function From Behavior CakePHP 2.10.12 Not Working

Hay. Currently I'm creating a function in Behaviour in CakePHP 2.10.12 as shown below :
<?php
App::uses('CakeTime', 'Utility');
App::uses('CakeNumber', 'Utility');
class ConverterBehavior extends ModelBehavior {
private $timezone;
private $locale;
private $currency;
function hellow() {
return "Hellow from behavior";
}
function initConverter($locale, $timezone, $currency) {
$this->locale = $locale;
$this->timezone = $timezone;
$this->currency = $currency;
setlocale(LC_ALL, $locale);
}
public function getCurrentLocale() {
return $this->locale;
}
function convertCurrency($currencyAmount) {
return CakeNumber::currency($currencyAmount, $this->currency);
}
function convertDate($date) {
return CakeTime::i18nFormat($date, null, false, $this->timezone);
}
}
?>
Then above behavior is used by my model as shown below :
<?php
class Test extends AppModel {
public $actsAs = array('Converter');
}
And then I call the function that I created from behavior in my Controller as shown below :
public function converterModel() {
$this->Test->initConverter('ja_JP', 'Asia/Tokyo', 'JPY');
$temp = $this->Test->convertCurrency(23456789901.123456);
debug($this->Test->hellow());
// $this->set('jpDate', $this->Test->convertDate(new DateTime));
}
The problem is initConverter cannot be initialized. I check the variabel that are inputed from controller and all of those variabel are null (it's weird). But when I call the hellow() (function in behavior), the result is displayed in my view. So is there something missing here ?
Thank you
Note :
This is the error message displayed in my view :
Look at the warning/notice, you are receiving an object where you expect a string/number.
The first argument of an externally invoked behavior method will always be the instance of the model that the behavior is attached to, ie your method signatures should be like:
function initConverter(Model $model, $locale, $timezone, $currency)
function convertCurrency(Model $model, $currencyAmount)
// etc...
See also
Cookbook > Models > Behaviors > Creating Behaviors
Cookbook > Models > Behaviors > Creating behavior methods

How would I change entity labels?

I use Symfony4 and Sonata admin. When I use ModelListType it worked as shown on the screenshot below.
How would I change entity item machine name: ('App\Entity\Product:000000003aaca7040000000026c8b335') to entity item field 'name' value?
My code for this field is:
#/project/src/Admin/ProductAdmin.php
...
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('name')
->add('category', ModelListType::class);
}
...
I have solve this by adding __toString() method to entity:
public function __toString(){
return $this->getName();
}
Just return the value directly by name instead of calling the getter method like,
public function __toString()
{
return $this->name;
}

Laravel - Display Array/String Object in view from database

Data are stored as ["item_1", "item_2"] in database like shown below.
I want to display those data in view blade properly.
Product Model
protected $fillable = ['name', 'prod_id'];
public function models() {
return $this->hasMany(Model::class, 'prod_id');
}
Model Model
protected $fillable = ['model', 'prod_id'];
protected $cat = ['model'=>'array'];
public function model()
{
return $this->belongsTo(Product::class, 'prod_id');
}
Controller - store method
public function create (Request $request, Product $product){
$models = new Model;
{
$model = json_encode(request('models'));
$items->models = $model;
$product->models()->save($models);
}
}
Controller show method
public function show(request $id){
$product = Product::findorfail($id);
$models = Model::with(['model'])->where('prod_id', $product->id)->get();
return view ('show', compact('product', 'models'));
Create View
<input type="checkbox" name="model[]" value="Samsung">
<input type="checkbox" name="model[]" value="Nokia">
<input type="checkbox" name="model[]" value="Apple">
<button>Add Model</button>
I tried show view:
#foreach($models as $model)
{{ json_decode($model->models) }}
#endforeach
It throws
htmlspecialchars() expects parameter 1 to be string, array given
What am I missing.
PS: MySQL does not support json column, so I saved as text column.
you need to do someting like this.
Model Model
protected $fillable = ['models', 'prod_id']; // screenshot says that the field name is "models"
protected $cast = ['models' => 'array']; // the property is $cast no $cat
public function product()
{
return $this->belongsTo(Product::class, 'prod_id');
}
ModelController - store method
public function store (Request $request){
$product = Model::create([
'models' => json_encode($request->models),
'prod_id' => $request->prod_id
]);
return redirect()->back()->with('success', 'created!');
}
public function show(Request $id){
$model = Model::findOrFail($id)->with('product');
return view ('model.show', compact('model'));
}
ProductController show method
public function show(request $id){
$product = Product::findOrFail($id)->with('models'); // the method name is findOrFail() no findorfail
// $models = Model::with(['model'])->where('prod_id', $product->id)->get();
return view ('show', compact('product'));
}
Into the show View
#foreach($product->models as $models)
#foreach(json_decode($models->models) as $model)
{{ $model }}
#endforeach
#endforeach
Your Models Model confuses me a little bit. You seem to have a field name model that's the same as a relationship method name. That means whenever you include that relation, it'd functionally override that property with data from the related table. (I say 'functionally' because you're using dynamic properties, whereas it is actually possible to explicitly tell Eloquent whether you want an attribute or relation without making it guess.)
That said, your $model->models property could be coming back as an array for one of two reasons. The first is that it may be accidentally referring to a relational data-set and not the JSON string you were expecting. The second is you've corrected the protected $cat = ['model'=>'array']; to read protected $cast = ['models'=>'array'];, and it's stepping on your toes now. By casting it to an array, it may be getting automatically get interpreted back into one before you call json_decode on it.
Either way, I'd dd($model->models) to see what it is first.
You need to change your foreach like this:
#foreach($models->models as $model)
{{ json_decode($model) }}
#endforeach
because Your array is like this
{"id":18,"prod_id":22,"models":{"id":22,"user_id":1}}
In here the $models is getting only id and prod_id models is still array so your foreach should be #foreach($models->models as $model)
Sample Code is here:
$arr = '{"id":18,"prod_id":22,"models":{"id":22,"user_id":1}}';
echo '<pre>';
foreach (json_decode($arr->models) as $str){
echo $str;
}

How to pass variable from controller to all view files (.ctp) in cakephp

My controller : Controller/appController/OrdersController.php
I have a function named nocontact() and I can pass variable to nocontact.ctp as follows:
$allNoContacts = $result;
$service_charge=$this->ServiceCharge->find('all');
$zero_service_charge=$this->ZeroServiceCharge->find('all');
$zero_service_charge=$zero_service_charge[0]['ZeroServiceCharge']['items'];
$this->set(compact('allNoContacts','service_charge','zero_service_charge'));
How can I pass this variable to all view files under OrdersController?
You can set the variable in beforeRender method of your OrdersController.
public function beforeRender() {
$this->set('name', 'value');
}

How do you set a scenario when doing a restful call in Yii2 to return certain fields

Im currently making a Yii2 RESTful system with AngularJs.
In my database i've got several columns that i want to be able to return when doing a particular call from a certain point in my system.
The problem i'm having is how do i return only a handful of fields eg(id, title and stub) from the restful call in another part of my system so that it ignores other fields in the table.
I would ideally like it to work in a similar way to how a Models rules work with scenarios in yii.
There are two methods, I think:
1. use params
// returns all fields as declared in fields()
http://localhost/users
// only returns field id and email, provided they are declared in fields()
http://localhost/users?fields=id,email
// returns all fields in fields() and field profile if it is in extraFields()
http://localhost/users?expand=profile
// only returns field id, email and profile, provided they are in fields() and extraFields()
http://localhost/users?fields=id,email&expand=profile
2. overriding model's fields()
// explicitly list every field, best used when you want to make sure the changes
// in your DB table or model attributes do not cause your field changes (to keep API backward compatibility).
public function fields()
{
return [
// field name is the same as the attribute name
'id',
// field name is "email", the corresponding attribute name is "email_address"
'email' => 'email_address',
// field name is "name", its value is defined by a PHP callback
'name' => function () {
return $this->first_name . ' ' . $this->last_name;
},
];
}
// filter out some fields, best used when you want to inherit the parent implementation
// and blacklist some sensitive fields.
public function fields()
{
$fields = parent::fields();
// remove fields that contain sensitive information
unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);
return $fields;
}
more detail, refer to https://github.com/yiisoft/yii2/blob/master/docs/guide/rest-resources.md
You may use scenarios method inside your model for this, but you will have to extend a bit toArray method in order to make it work properly:
public function scenarios()
{
return array_merge(parent::scenarios(), [
'simple_info' => [
'email',
'name',
],
'login' => [
'id',
'email',
'name',
'auth_token',
],
]);
}
public function toArray(array $fields = array(), array $expand = array(), $recursive = true)
{
$scenarios = $this->scenarios();
$scenario = $this->getScenario();
if (!empty($scenarios[$scenario])) {
$data = parent::toArray($fields, $expand, $recursive);
return array_intersect_key($data, array_flip($scenarios[$scenario]));
}
return parent::toArray($fields, $expand, $recursive);
}
After this you may simply do something like this:
$model = new LoginForm();
if ($model->load(Yii::$app->request->post(), '') && $model->login()) {
$user = $model->getUser();
// Lets change scenario to login in order to get `auth_token` for authorization
$user->setScenario('login');
$user->generateAuthKey();
$user->save(FALSE);
return $user;
} else {
return $model;
}
As a side note (expanding on the answer from #Ganiks), if you are manually returning the list of Models, you will need to return them as a DataProvider (rather than simply as an array of Models) for the fields parameter to have an effect.
For example, if you do something like this...
class UserController extends yii\rest\Controller
{
public function actionIndex()
{
return User::find()->all(); // Not what you want
}
// ...
}
... then the fields parameter will not have the desired effect. However, if you instead do this...
class UserController extends yii\rest\Controller
{
public function actionIndex()
{
return new ActiveDataProvider([
'query' => User::find(),
'pagination' => false,
]);
}
// ...
}
... then the returned fields will only be those you specified in the fields parameter.

Resources