I am new on cakephp. I have done all the required steps but still having trouble in saving data in database with cakephp
code of adduser function from Articlecontroller.php:
public function adduser()
{
$user = $this->Users->newEntity();
if ($this->request->is('post')) {
$user = $this->Users->patchEntity($user, $this->request->getData());
// Hardcoding the user_id is temporary, and will be removed later
// when we build authentication out.
$user->user_id = 1;
if ($this->Users->save($user)) {
$this->Flash->success(__('Your article has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('Unable to add your article.'));
}
$this->set('article', $user);
}
code of UserTable model:
<?php
// src/Model/Table/ArticlesTable.php
namespace App\Model\Table;
use Cake\ORM\Table;
class UsersTable extends Table
{
public function initialize(array $config)
{
$this->addBehavior('Timestamp');
}
}
Data Base Table onto my locahost:
I think you forgot to load User model in controller. It should be fixed adding this line in function adduser() before first line. It should look like this.
public function adduser()
{
$this->loadModel('Users');
$user = $this->Users->newEntity();
...
Cakephp documentation.
https://book.cakephp.org/3.0/en/controllers.html#loading-additional-models
Well, you need to have a CakePHP application that is using the plugin. You need to add $this->loadComponent('Auth'); to your AppControllers initialize() method and configure it properly.
I highly recommend you to do the complete blog tutorial of the official CakePHP documentation or you won't have much fun with any plugin or anything else in the framework. It covers setting up Auth as well.
As other have started, when not in the controller related to the table you're accessing, you need to load the model and its related entities.
The current way of retrieving a table is through the table registry, as shown below:
use Cake\ORM\TableRegistry;
// Now $articles is an instance of our ArticlesTable class. This is how CakePHP 4 prefers it.
$articles = TableRegistry::getTableLocator()->get('Articles');
// Prior to 3.6.0
$articles = TableRegistry::get('Articles');
So for your public method, it should look like this:
public function adduser()
{
$usersTable = TableRegistry::getTableLocator()->get('Users');
$user = $usersTable->newEntity();
if ($this->request->is('post')) {
...code for handling post...
}
}
The CakePHP 3.x (and beyond) documentation regarding ORM outlines this well. While $this->loadModel('Articles') work, a quick search through the docs shows it is not frequently referred to neither in ORM section nor in examples.
Related
I can't store name and IP address to DB. I created a table 'info' with appropriate fields by running php artisan migrate.
A schema
Schema::create('info', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('ip');
$table->timestamp('created_at')->nullable();
});
A model for Info
class Info extends Model
{
protected $fillable = ['ip', 'name'];
}
Maybe the problem is in my HomeController where I get those variables?
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Info;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Request;
class HomeController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function store(Request $request) {
Info::create(['info' => $request->input('info')]);
}
public function index()
{
if (Auth::check())
{
$name = Auth::user()->name;
$ip = Request::ip();
\App\Events\eventIp::dispatch($ip,$name);
return view('home');
}
}
}
My routes in web.php
Route::post('/home','HomeController#store');
Route::get('/home', 'HomeController#index')->name('home');
});
But it doesn't work. Gives no errors and no records in DB.
Something make me think that it have to do with my index function. I got info in function index and maybe function store doesn't have a clue what I mean.
A controller action is basically a method that usually gets executed when you open an url (as you connect them to routes).
In your example you have connected two routes to their respective actions:
Route::post('/home','HomeController#store');
Route::get('/home', 'HomeController#index')->name('home');
Now, when you log in succesfully, imagine that you end up in the page with url http://localhost:8000/home in your web browser.
The key difference is the method which you use to call your route (you can get an overview of the differences here), in your case you are using GET method.
The resulting action executed it the one associated to /home route with the GET method, that is the HomeController#index action (or method).
The store method, although is in the same HomeController class, doesn't get triggered unless you execute the /home route, but with the POST method.
You can confirm that if you put a debug message in each of the methods like this:
class HomeController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function store(Request $request)
{
echo 'I will not be executed';
}
public function index()
{
echo 'I have been executed';
}
}
If you want to simply save a info record when you visit the /home route with the GET method, you can put the save in the index method itself and get rid of the store method:
class HomeController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
// You can omit Auth::check() because you are using the auth middleware
// that exactly does this job.
Info::create([
'name' => Auth::user()->name,
'ip' => Request::ip(),
]);
return view('home');
}
}
Keep in mind that doing in this way you will get a new database record for each page view you make to that route (if you keep refreshing the page, you should see new records being added to database).
Update
When you use Eloquent Models, laravel will look for a table named after the pluralized model name (Info model will try to use infos table).
However you created a table named info. To solve that you can either rename the table and rerun the migration with php artisan migrate:refresh (it will delete all the existing data in the database you are using for your laravel app)
Or specify the table name to use for that laravel model:
class Info extends Model
{
protected $table = 'info';
protected $fillable = ['ip', 'name'];
}
How are you calling the functions? There is a couple of things wrong with your code, but you're saying there are no errors at all.
Firstly, your Info::create call does not need the ['info' => $request->input('info')] info. This is because your Info model has no database property called info, but normally you would get an obvious error with the approach, which is why I expect you are also calling the store method incorrectly.
Call the create method like so:
$infoModel = Info::create(['name' => $request->input('name'), 'ip' => $request->input['ip']]);
or, if you can guarantee your $request only contains the needed fields (properly validated), you can just do
$infoModel = Info::create($request->all());
Add a little more info to the question on how you are calling store and we can probably solve the rest of your problem.
Within your store function inside HomeController , use
Info::create([
'name' => Auth::user()->name,
'ip' => Request::ip(),
]);
and make sure Info model is imported.
Also make sure your route has the call to store function while POSTing data .
I'm trying to create Rest API without view and planning to use these api's in angular 2 application. does have any idea about it?
Cake makes this incredibly easy. A few things I have learned building without views.
Set the _serialize variable
$data = ['cheeses' => ['gouda', 'pepper jack', 'cheddar']];
$this->set('responseData', $data);
$this->set('_serialize', 'responseData');
Throw bad request exceptions and other network related exceptions
Cake will render nice json views for you.
Set your accept header when issuing and ajax request to be application/json
You can use cake prefixes for api versions
Look at Stateless Authentication for your api
In your AppController.php, with these parameters, all of your controllers will be render in json
public function beforeRender(Event $event)
{
$this->RequestHandler->renderAs($this, 'json');
$this->response->type('application/json');
$this->set('_serialize', true);
}
CakePHP will render json easily.
In your Controller,look like something.
protected $responseBody = [];
public function beforeRender(Event $event){
foreach($this->responseBody as $responseKey=>$response){
$this->set($responseKey, $response);
}
$this->set('_serialize', array_keys($this->responseBody));
}
public function initialize()
{
parent::initialize();
$this->RequestHandler->renderAs($this, 'json');
}
public function index(){
$this->request->allowMethod(['get']); // Method like post,get..
$this->responseBody["statusCode"] = 200;
$this->responseBody["statusDescription"] = ''; //You send any text in json.
$this->responseBody["data"] = []; // All data that you can send.
}
For further informations , You can see CakePHP Cookbook REST API to click here
I am trying to modify FormHelper's behaviour to meet my application requirements. I would like to use native FormHelper but for all input I need to add some short message providing help to the user and describing the particular field.
My idea is to create my own helper and pass a help message as an argument. This function will modify form's inputDefaults setting and call a native FormHelper input function.
For example:
class MsgFormHelper extends AppHelper {
public function input($name, $message, $options) {
$this->_View->Form->_inputDefaults['after'] .= '<div>'.$message.'</div>';
return $this->_View->Form->input($name, $options);
}
}
But this solution notices this error:
Notice (8): Indirect modification of overloaded property
FormHelper::$_inputDefaults has no effect...
Is there some way how to modify "after" value in form's inputDefaults setting?
I probably found a solution (it works but I am not sure it doesn't violate some CakePHP's principles). Thanks for your opinions.
class MsgFormHelper extends AppHelper {
public function __construct(View $view, $settings = array()) {
parent::__construct($view, $settings);
}
public function input($name, $message, $options) {
$add_message = true;
if (isset($options['after'])) {
$options['after'] = trim($options['after']);
$add_message = empty($options['after']);
}
if ($add_message) {
$options['after'] = '<div class="input-help">' . $message . '</div>' . $this->_View->Form->_inputDefaults['after'];
}
return $this->_View->Form->input($name, $options);
}
}
You should be extending the FormHelper itself not AppHelper. Then in your controller use the aliasing feature so that you still use $this->Form->input() in your views but it would actually refer to your custom helper.
public $helpers = array('Form' => array('className' => 'MsgForm'))
I'm new to CI but I know CakePHP pretty well. I've searched the documentation of CI and haven't found this.
In CakePHP the fields "created" and "modified" were automatically populated by the "save" function. Does CI have two fields like that? Or can he automatically populate something?
EDIT:
Ok.. I've extended the CI_Model class and now, is there a function such as beforeSave (from cake)? And shouldn't I rather extend the DB class (I use db->set and db->insert);
Is this ok?
<?php
class spj_Model extends CI_Model {
var $table;
function __construct() {
parent::__construct();
}
function insert($data) {
$this->load->helper('date');
$data['created'] = date('Y-m-d H:i:s',now());
$data['modified'] = date('Y-m-d H:i:s',now());
return $this->db->insert($this->table,$data);
}
function update($data,$where=array()) {
$this->load->helper('date');
$data['modified'] = date('Y-m-d H:i:s',now());
return $this->db->ubdate($this->table,$data, $where);
}
}
On this page, a user would see a list of links which he himself/herself has posted, not including the rests which were posted by others. I'm in the middle of writing the function in one of my models, e.g. news
I am trying to use the idea of a dashboard: http://nuts-and-bolts-of-cakephp.com/2008/12/16/how-to-build-a-dashboard-for-your-application-in-cakephp/
I created my dashboards controller as:
function index () {
$this->set('news', ClassRegistry::init('News')->showmy());
}
// In my news::model I have a function called showmy()
function showmy() {
$userid = $this->Session->read('Auth.User.id');
$mynews = $this->News->find('all', array('conditions' => array('News.user_id' => '$userid')));
$this->set('mynews', $mynews);
}
//The error I get is as follow
Undefined property: News::$Session [APP\models\news.php, line 7]
Fatal error: Call to a member function read() on a non-object in C:\...\app\models\news.php on line 7
I know something is terribly wrong with the showmy function, can someone shed some light how do we write the function that only retrieves the posts by one user? or if the problems are minor, correct the function above?
Try this
You can't use Session from model so passit from controller
function index () {
$userid = $this->Session->read('Auth.User.id');
$this->set('news', ClassRegistry::init('News')->showmy($userid ));
}
function showmy($userid) {
return $this->find('all', array('conditions' => array('News.user_id' => $userid)));
}
My approach seems to be more documentation-like:
Let say you have PostsController with Post Model. When you do index on posts it's fine, you query for all posts. But for one user, I think you mean single index action in PostsController like:
class Post extends AppModel {
public $belongsTo = 'User'; // This way you're telling cakephp that one user can have many posts (he's posts' author)
}
class PostsController extends AppController {
public function viewByUser() {
$id = $this->Auth->user('id');
$posts = $this->Post->findAllById($id);
$this->set('posts', $posts);
}
}
And then, in your view, you build a table like for index action
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#magic-find-types