I want to pass an object of Student Model to a view in Laravel. I tried using
return view('student/main')->with($student);
Where $student is a instance of Student Model (Code is below)
But it gave an error "Illegal offset type"
I know that data can be passed as an array to a view. But I really want to pass it as a object if possible. Then I can display data as follows by fetching data from get methods.
<h4 class="text-left"><strong>{{$student->getName()}}</strong> </h4>
I am looking for a solution which can be done using keeping objects instead of arrays.(if possible)
The Student model code is as follows. It consists with simply setters and getters.
class Student extends Model{
//attributes
private $student_id;
private $first_name;
private $last_name;
private $batch_id;
// set attributes
public function setID($student_id)
{
$this->student_id = $student_id;
}
public function setFirstName($first_name)
{
$this->first_name = $first_name;
}
public function setLastName($last_name)
{
$this->last_name = $last_name;
}
public function setBatchID($batch_id)
{
$this->batch_id = $batch_id;
}
// get attributes
public function getName()
{
return $this->first_name." ".$this->last_name;
}
public function getID()
{
return $this->student_id;
}
public function getBatchID()
{
return $this->batch_id;
}
You've got a number of options to do that
return view('student/main', ['student'=> $student]);
return view('student/main', compact('student'));
return view('student/main')->with('student', $student);
return view('student/main')->withStudent($student);
You have to name your variable:
return view('student/main')->with(['student' => $student]);
Related
I can not load data to properties using this construction I receive null in dump
<?php
namespace App\Domain\Good;
class GoodDto
{
public $name;
public $articul;
public $price;
public $type;
public $qnt;
public $discount;
public $category;
public $description;
public $description2;
public $color;
public function load($data)
{
$this->name = $data['name'];
$this->articul = $data['artikul'];
$this->price = $data['price'];
$this->type = (isset($data['type'])) ? $data['type'] : null;
$this->qnt = $data['count'];
$this->discount = $data['spinner-decimal'];
$this->category = $data['id_cat'];
$this->description = $data['editor1'];
$this->description2 = '';
$this->color = $data['color'];
//$this->user_id = Auth::user()->id;
}
public static function fromRequest($request)
{
dump('inp=>',(new self ())->load($request->input()));
return (new self ())->load($request->input());
}
}
Please explain to me why I receive null while request->input() is an array, I call it from another place
$dto=GoodDto::fromRequest($request);
Method chaining, returns the last return from the chain. The other returns are used to call the next link in the chain.
(new self ())->load()
So load() needs to return $this
public function load($data)
{
...
return $this;
}
Currently it returns null, which is why it returns null.
See you are not saving the instance from the constructor, instead you pass it to load by enclosing it within the (....). By pass it I mean you call the load method on the return from the constructor.
You can test this like so:
class foo{
function load(){
return $this;//return this
}
}
var_dump((new foo)->load());
class bar{
function load(){
//return null
}
}
var_dump((new bar)->load());
Output
//return this
object(foo)#1 (0) {
}
//return null
NULL
sandbox
The second class in the example above class bar, is essentially what you are doing.
PS. forgot to scroll down on your post at first ... lol ... So I had to update my answer.
Bonus
You can also simplify the load code like this:
public function load($data)
{
foreach($data as $prop=>$value){
if(property_exists($this,$prop)) $this->$prop = $value;
}
return $this;
}
This way if you add new properties you don't have to edit the load method ever again, you just have to name the array elements the same as the class properties. You can even throw an error if the property does not exist if you want, by adding an else to the condition etc...
Personally, when I do this I prefer to call a set method like this:
//eg. $data = ['foo' => '2019-06-16']
public function load(array $data)
{
foreach($data as $prop=>$value){
$method = 'set'.$prop; //$method = 'setfoo' using the example above
if(method_exists($this,$method )){
$this->$method($value); //calls 'setfoo' with '2019-06-16'
}else{
throw new Exception('Unknown method '.$method);
}
}
return $this;
}
public function setFoo($date){
$this->foo = new DateTime($date);
}
Then you can apply some transforms to the data etc... PHP method names are not case sensitive. You can even combine these by first checking for a method then a property then throw the error etc...
Cheers.
Ok so currently have this function in controller, which is called multiple times.
public function formatFloat($value)
{
return (float)sprintf('%0.6f', $value);
}
So I am trying to use getters and setters so I can just use
$model->$whatever;
and the formatting will be done.
In my model I have
public function getChargePeak()
{
return $this->charge_peak;
}
public function setChargePeak($value)
{
return $this->charge_peak = (float)sprintf('%0.6f', $value);
}
but when doing
$peak = $model->chargepeak;
var_dump($peak);die;
it is still returning as a string
If the charge_peak property is stored as string and you need a float in you app you should use
public function getChargePeak()
{
return floatval($this->charge_peak);
}
Anyway you should store the values in a coherent way as you use the values in your app ..
http://php.net/manual/en/function.floatval.php
So I suggest u another pattern: decorator and helpers. You should use a controller only to get data from request, prepare it for model and send it to view.
Formatting values is a helper logic. So create a new class
\common\helpers\Number.php
namespace common\helpers;
class Number
{
public static function formatFloat($value)
{
return (float)sprintf('%0.6f', $value);
}
}
Then create decorator for your model:
namespace common\models\decorators;
class YourModelDecorator
{
/**
* YourModel
*/
private $model;
public function __construct(YourModel $model)
{
$this->model = $model;
}
public function __get($name)
{
$methodName = 'get' . $name;
if (method_exists(self::class, $methodName)) {
return $this->$methodName();
} else {
return $this->model->{$name};
}
}
public function __call($name, $arguments)
{
return $this->model->$name($arguments);
}
public function getChargePeak()
{
return \common\helpers\Number::formatFloat($this->model->charge_peak);
}
}
and send it to view for example:
public function actionView($id)
{
$model = $this->loadModel($id);
$this->render('view', [
'model' => new \common\models\decorators\YourModelDecorator($model)
]);
}
I want to create custom userIdentity class according to my specific requirements .Here the code is
<?php
namespace app\models;
use yii\web\IdentityInterface;
use app\models\dbTables\Users;
class UserIdentity implements IdentityInterface{
const ERROR_USERNAME_INVALID=3;
const ERROR_PASSWORD_INVALID=4;
const ERROR_NONE=0;
public $errorCode;
private $_id;
private $_email;
private $_role;
private $_name;
public function findIdentityById($id){
$objUserMdl = new Users;
$user = $objUserMdl::findOne($id);
$userRole = $objUserMdl->getUserRole($user->user_id);
$this->_id = $user->user_id;
$this->_email = $user->email_address;
$this->_role = $userRole;
$this->_name = $user->full_name;
return $this;
}
public function getId()
{
return $this->_id;
}
public function getName(){
return $this->_name;
}
public function getEmail(){
return $this->_email;
}
public function getRole(){
return $this->_role;
}
public static function findIdentity($id)
{
return self::findIdentityById($id);
}
public function getAuthKey()
{
throw new NotSupportedException('"getAuthKey" is not implemented.');
}
public function validateAuthKey($authKey)
{
throw new NotSupportedException('"validateAuthKey" is not implemented.');
}
public static function findIdentityByAccessToken($token, $type = null)
{
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
}
?>
Basically I have two tables roles and users and I want to set the specific properties from both table in yii::$app->user->identity
When I call the above code the findIdentity($id) function returns error for obvious reasons stating that I cannt call $this in static funtion . How can I set the required properties in function and return the instance of userIdentity class from it ?
I recommend reading this: When to use self over $this? you are really confusing the 2.
$objUserMdl = new Users;
$user = $objUserMdl::findOne($id);
$userRole = $objUserMdl->getUserRole($user->user_id);
You are calling :: on an object, you cannot do that.
I say delete what you have done and start again, it should be much easier then what you wrote. It would take a long time to show you how to do it properly, just look in the yii2 advance template and see how they are doing it. You can use your own identity class and set up any special attributes there. Just study the yii2 code.
I would like one of the attributes of my object to be an array of another type of object.
How do I represent this (i.e. public $someObjectArray;)
What would be the syntax to add an entry to this attribute?
What would be the syntax to reference the object?
To provide some (hopefully) useful context.
Lets assume that the object is property which has some attributes one of which is a number of tenants who will have their own properties like name, age etc...
class Tenant {
// properties, methods, etc
}
class Property {
private $tenants = array();
public function getTenants() {
return $this->tenants;
}
public function addTenant(Tenant $tenant) {
$this->tenants[] = $tenant;
}
}
If the Tenant model has some sort of identifiable property (id, unique name, etc), you could factor that in to provide better accessor methods, eg
class Tenant {
private $id;
public function getId() {
return $this->id;
}
}
class Property {
private $tenants = array();
public function getTenants() {
return $this->tenants;
}
public function addTenant(Tenant $tenant) {
$this->tenants[$tenant->getId()] = $tenant;
}
public function hasTenant($id) {
return array_key_exists($id, $this->tenants);
}
public function getTenant($id) {
if ($this->hasTenant($id)) {
return $this->tenants[$id];
}
return null; // or throw an Exception
}
}
I have a Yii model that will be using (later) multiple databases and the table prefix will be based on a code.
For example:
AMI_tablename, BMI_ AMI_tablename etc
These all tables are same but in different databases.
I want to know how could I provide the dynamic table name to Yii model at run time?
I tried to using a setter function but the parent class CActiveRecord gives an error as it does not get the value from the child model class.
so here is my model code (only the part I have problem)
class RevShareModel extends CActiveRecord
{
public $prefix;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
/**
* #return string the associated database table name
*/
public function tableName()
{
return $this->prefix . '_revshare_model';
}
now somewhere in my controller
$obj = RevShareModel::model();
$obj->prefix ="BMI";
$obj->tableName();
$obj->findByPk(1);
exit;
But what I get the error is:
CDbException
The table "_revshare_model" for active record class "RevShareModel" cannot be found in the database.
C:\wamp\www\framework\db\ar\CActiveRecord.php(2264)
seems like when tableName() method is called by CActiveRecord it does not get $prefix.
You've got such error because the table name is actually stored in model's metadata. You can see that by checking contents of $model->getMetaData() which returns CActiveRecordMetaData object. To refresh metadata you should call $model->refreshMetaData() after changing the 'prefix' attribute of your model, e.g.:
...
$obj->prefix ="BMI";
$obj->refreshMetadata();
...
This will definitely do the trick.
You have to override the CActiveRecord::tableName method (probably in an abstract base class for your models). Here's what it does by default:
public function tableName()
{
return get_class($this);
}
And here's what you could change it to:
abstract class MyActiveRecord extends CActiveRecord
{
public $prefix; // should probably be private, your call
public function tableName()
{
return $prefix.'_'.get_class($this);
}
}
This is how I've solved that problem.
private static $_tableName;
public function __construct($tableName)
{
if(strlen($tableName) == 0)
{
return false;
}
if(strlen($tableName)>0){
self::$_tableName = $tableName;
}
self::setIsNewRecord(true);
}
public static function model($tableName)
{
if(strlen($tableName) == 0)
{
return false;
}
$className=__CLASS__;
if(strlen($tableName)>0){
self::$_tableName = $tableName;
}
return parent::model($className);
}
public function tableName()
{
return '{{'.self::$_tableName.'}}';
}
public function setTableName($tableName)
{
self::$_tableName = $tableName;
}
...
When I use this model, I simply put the name of the table in brackets:
$model = new ClassName($tableName);
I have same problem.
I have a model, but I want the data to be saved in different table .So I change the table name before save the data.
public $tbl_name = 'tbl_user_1';//default table
public function tableName()
{
return $this->tbl_name;
}
public function saveDataReg(){
$mKey = $this->selfMHash($this->username);
$modKey = $mKey % 2;
$this->tbl_name = 'tbl_user_' . $modKey;
$this->refreshMetadata();//change the default Metadata
$this->save();
}
public function selfMHash($key){
$md5 = substr(md5($key), 0, 8);
$seed = 31;
$hash = 0;
for($i=0; $i<8; $i++){
$hash = $hash * $seed + ord($md5{$i});
$i++;
}
return $hash & 0x7FFFFFFF;
}
Now I find the Metadata not be changed when the function of refreshMetadata be used.
Last I change the original code
public function refreshMetaData()
{
$finder=self::model(get_class($this));
$finder->_md=new CActiveRecordMetaData($finder);
if($this!==$finder)
$this->_md=$finder->_md;
//return var_dump($this);
}
public function new_refreshMetaData()
{
$finder=self::model(get_class($this));
$finder->_md=new CActiveRecordMetaData($this);
if($this!==$finder)
$this->_md=$finder->_md;
//return var_dump($this);
}
I override the function of refreshMetaData and chage the param of CActiveRecordMetaData.
$this->new_refreshMetadata();//use new function
Then it worked.
I don't understand the reason of problem.
You can use with MyModel::model()->tableName(), but please don't forget write {{table}}.