How to Add to Table from Another Controller Cakephp 3 - cakephp-3.0

I'm new to cakephp3. I would like to know if it is possible to add a new entry form controller1 to table2.
It is a login form. So I would like to authenticate first whether the user is registered, then after authenticating, I would like to save the details to another table.
class UsersController extends AppController
{
public function login()
{
$user = $this->Users->newEntity();
if($this->request->is(['post']))
{
$user = $this->Auth->identify();
if($user)
{
$logs = TableRegistry::get('AttendsTable');
$log->username = 'lorem ipsum';
$log->datenow = '2018-11-10';
$log->tin = '12:42:00';
$log->tout ='12:42:00';
$logs->save($log);
$this->Auth->setUser($user);
$this->redirect(['action'=>'index']);
}
}
}
I am getting an error:
"Argument 1 passed to Cake\ORM\Table::save() must implement interface Cake\Datasource\EntityInterface, instance of stdClass given, called in C:\xampp\htdocs\TimeStamps\src\Controller\UsersController.php on line 32"

Your code isn't working because the Model->save() function expects an entity. In your snippet $log is not defined first, so PHP just makes it a stdClass (gotta love high-level programming :p).
Something like this should work:
$logs = TableRegistry::get('AttendsTable');
$log = $logs->newEntity([
'username' => 'lorem ipsum',
'datenow' => '2018-11-10',
// ...
]);
$logs->save($log);
Moreover, I've heard say it's better to use $this->loadModel() instead of TableRegistry::get():
$this->loadModel('ExternalModel');
// Now available:
$this->ExternalModel->//...
Cookbook > Controllers > Loading Additional Models

Related

Create dynamic request object in Laravel

I was looking for help creating an object of the type Illuminate\Http\Request. This article helped me understand the mechanism of the class, but I did not get the desired result.
Create a Laravel Request object on the fly
I'm editing the development code passed to me by the customer. The code has a function that gets a request parameter from vue and translates it to JSON:
$json = $request->json()->get('data');
$json['some_key'];
This code returned an empty array of data:
$json = $request->request->add([some data]);
or
$json = $request->request->replace([some data]);
this one returned an error for missing the add parameter
$json = $request->json->replace([some data]);
A variant was found by trying and errors. Maybe, it help someone save time:
public function index() {
$myRequest = new \Illuminate\Http\Request();
$myRequest->json()->replace(['data' => ['some_key' => $some_data]]);
$data = MyClass::getData($myRequest);
}
..
class MyClass extends ...
{
public static function getData(Request $request) {
$json = $request->json()->get('data');
$json['some_key'];
In addition, there are other fields in the class that you can also slip data into so that you can pass everything you want via Request
$myRequest->json()->replace(['data' => ['some_key' => $some_data]]);
..
$myRequest->request->replace(['data' => ['some_key' => $some_data]]);
..
$myRequest->attributes->replace(['data' => ['some_key' => $some_data]]);
..
$myRequest->query->replace(['data' => ['some_key' => $some_data]]);
$myRequest = new \Illuminate\Http\Request();
$myRequest->setMethod('POST');
$myRequest->request->add(['foo' => 'bar']);
dd($request->foo);
This from the link you shared works, give it a try. Thanks for sharing that link!

Retrieve specific data using JSON decode Laravel

I'm new to Laravel. I need to retrieve specific data from the database using the JSON decode. I am currently using $casts to my model to handle the JSON encode and decode.
This is my insert query with json encode:
$request->validate([
'subject' => 'required|max:255',
'concern' => 'required'
]);
$issue = new Issue;
$issue->subject = $request->subject;
$issue->url = $request->url;
$issue->details = $request->concern;
$issue->created_by = $request->userid;
$issue->user_data = $request->user_data; //field that use json encode
$issue->status = 2; // 1 means draft
$issue->email = $request->email;
$issue->data = '';
$issue->save();
The user_data contains {"id":37,"first_name":"Brian","middle_name":"","last_name":"Belen","email":"arcega52#gmail.com","username":"BLB-Student1","avatar":"avatars\/20170623133042-49.png"}
This is my output:
{{$issue->user_data}}
What I need to retrieve is only the first_name, middle_name, and last_name. How am I supposed to achieve that? Thank you in ADVANCE!!!!!
As per the above code shown by you it will only insert data into the database.For retrieving data you can make use of Query Builder as i have written below and also you can check the docs
$users = DB::table('name of table')->select('first_name', 'middle_name', 'last_name')->get();
I will recommend using Resources. It really very helpful laravel feature. Check it out. It is a reusable class. You call anywhere and anytime.
php artisan make:resource UserResource
Go to your the newly created class App/Http/Resources/UserResource.php and drfine the column you want to have in your response.
public function toArray($request) {
return [
"first_name" => $this->first_name,
"middle_name" => $this->middle_name,
"last_name" => $this->last_name
]
}
Now is your controller you can use the UserResource like folow:
public function index()
{
return UserResource::collection(User::all());
}
Or after inserting data you can return the newly added data(f_name, l_name...)
$user = new User;
$user->first_name= $request->first_name;
$user->middle_name= $request->middle_name;
$user->last_name= $request->last_name;
$user->save();
$user_data= new UserResource($user);
return $user_data;

Laravel: Store error messages in database

Any one know how to send error messages to database in laravel which generate from app/exceptions/handler.php ?
I need to send what error massages generated in report() method to database.
If you are interested doing this manually, you can do something as following.
Step 1 -
Create a model to store errors that has a DB structure as following.
class Error extends Model
{
protected $fillable = ['user_id' , 'code' , 'file' , 'line' , 'message' , 'trace' ];
}
Step 2
Locate the App/Exceptions/Handler.php file, include Auth, and the Error model you created. and replace the report function with the following code.
public function report(Exception $exception) {
// Checks if a user has logged in to the system, so the error will be recorded with the user id
$userId = 0;
if (Auth::user()) {
$userId = Auth::user()->id;
}
$data = array(
'user_id' => $userId,
'code' => $exception->getCode(),
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'message' => $exception->getMessage(),
'trace' => $exception->getTraceAsString(),
);
Error::create($data);
parent::report($exception);
}
(I am demonstrating this using laravel 5.6)
Because Laravel uses Monolog for handling logging it seems that writing Monolog Handler would be the cleanest way.
I was able to find something that exists already, please have a look at monolog-mysql package. I did not use it, so I don't know whether it works and if it works well, but it's definitely good starting point.

Yii2 codeception dataFile fixture can't be found

I am trying to run simple test and insert two record in db via fixture dataFile.
What I get is :
[ReflectionException] Class C:\xampp\htdocs\codeception\frontend\tests/_data\user.php does not exist
The file is obviously there. My UserTest.php looks like this:
<?php
class UserTest extends \Codeception\Test\Unit
{
public function _fixtures()
{
return [
'class' => \frontend\tests\fixtures\UserFixture::className(),
'dataFile' => codecept_data_dir() . 'user.php'
];
}
public function testValidation()
{
$user = new \common\models\User();
$user->setUsername(null);
$this->assertFalse($user->validate(['username']));
$user->setUsername('aaaaaaaaaaaaaaaaaaaaaaaaaa');
$this->assertFalse($user->validate(['username']));
$user->setUsername('toma');
$this->assertTrue($user->validate(['username']));
}
public function testIfUserExist()
{
$this->tester->seeRecord('user', ['name' => 'Toma']);
}
}
I saw the linux like forward slash in the error but don't know how to change it. Not sure if this is the problem because I had the same path with some images and it was fine then. What can cause this ? Thank you!
You're using seeRecord() in a wrong way. First argument needs to by class name, including namespace, so you should use it like this:
$this->tester->seeRecord(\frontend\models\User::class, ['name' => 'Toma']);

Action after loginByCookie()

In my app, I'm using session to store some user's data (e.g. name, role). I'm using default User class on common/models from yii2 and I'm getting the data I need by user id.The problem is that the data I stored in session are lost if user resume their previous session without entering password (using remember me option). To solve this, I tried to modify and put the codes for saving user's data inside validateAuthKey() method in User since it's called when yii2 checking for authkey to resume session. As in:
public function validateAuthKey($authKey)
{
$user = Member::findOne(['account_id' => Yii::$app->user->id]);
// Save on session
Yii::$app->session->set('name', $user->first_name . ' ' . $user->last_name);
Yii::$app->session->set('position', $user->position);
// .. other data
return true;
}
As you can see, I use the id of logged user to find Member. But by doing this, I got "Trying to get property of non-object" exception from Yii::$app->user->id. I can only get the id after the login process is completed. After prying around, I found that loginByCookie() from User in vendor\yiisoft\yii2\Web is used to log in. Is there any way to save user's data without tampering codes on vendor? Maybe some kind of event after loginByCookie() is executed.
Create your own User model extends \yii\web\User
namespace frontend\components;
class User extends \yii\web\User
{
protected function afterLogin($identity, $cookieBased, $duration)
{
...Do something here...
parent::afterLogin($identity, $cookieBased, $duration);
}
}
Modify the config (main.php).
'components' => [
'user' => [
'class' => 'frontend\components\User',
'identityClass' => 'common\models\User',
...
]
]
Put the below code in common/config/bootstrap.php
The EVENT_AFTER_LOGIN will be called even if the user is logged in by cookie.
use yii\web\User;
use yii\base\Event;
Event::on(User::className(), User::EVENT_AFTER_LOGIN, function() {
$user = Member::findOne(['account_id' => Yii::$app->user->id]);
// Save on session
Yii::$app->session->set('name', $user->first_name . ' ' . $user->last_name);
Yii::$app->session->set('position', $user->position);
});