I have to maintenance the cakephp 3 project and in this project, they have create newEntity using array variable and then data are not save into database. I set print_r to get result of userModel but it doesn't show anything.
I was using nginx server (not apache), mysql 5.6, cakephp 3.
Here is the code what they used.
$userModel = $this->newEntity($tableData);
print_r($userModel);
if (!$userModel->errors()) {
$result = $this->save($userModel);
if ($result)
{
return $result->id;
}
} else {
return false;
}
There are two things you need to check first.
Try outputting the $tableData variable and ensuring the elements in it match up against the data structure you have for the model object you're trying to create.
To manipulate the entity. You should be calling it using
$this->ModelName->newEntity($tableData);
$this->ModelName->save($userModel)
You need call the model name to generate a new entity and to save it.
If your model name are $tableData:
Replace your $this->newEntity($tableData) to $this->$tableData->newEntity();
and your $this->save($userModel) to $this->$tableData->save($userModel);
Related
So, I have the following code:
$homepage = Homepage::first();
if (!$homepage) {
$homepage = new Homepage;
}
$homepage->first_presta_title = $request->first_presta_title;
$homepage->first_presta_content = $request->first_presta_content;
$homepage->second_presta_title = $request->second_presta_title;
$homepage->second_presta_content = $request->second_presta_content;
$homepage->third_presta_title = $request->third_presta_title;
$homepage->third_presta_content = $request->third_presta_content;
$homepage->shiatsu_text = $request->shiatsu_text;
$homepage->shiatsu_image = $request->shiatsu_image;
$homepage->doin_text = $request->doin_text;
$homepage->doin_image = $request->doin_image;
$homepage->save();
Everything works, but I wanted to see if there weren't any better way to save datas without asigning every single element to its column, then I found out someone answering to a question by using the following code:
$homepage->save($request->all());
So I tried it by myself, but nothing happened: no error, but also nothing saved in my database.
So, is there any fastest way to save datas ? Is it possible to use a loop to save everything?
Thank you in advance
When you use save(), you are actually using Mass assignment. So, either you explicitly define all the fields in your model to be mass assignable or you could use create() instead.
However, in your particular case, the whole method could be cleaned up to just one line:
return Homepage::updateOrCreate($request->all());
If you want the model to autofill based on a given array you need to create a new model entity Like this
$homepage = HomePage::create($request->all());
$homepage->save()
If you give an array to save() it expects the options for saving not for values to assign
Source:
laravel api docs for model/save()
laravel api docs for model::create()
I'm making a simple API endpoint that returns an access code for an event.
If the event does not have access code, then it gets assigned one and saved in the database. Then, it checks if it's currently public or private. If private, return access code, if public, return empty string.
This is the endpoint controller:
public function getAc($eventId) {
// Pull event
$event = $this->eventService->api->getEventForce($eventId);
// If no access code for the event, generate one and update event record accordingly
if ($event->access_code == null) {
$access_code = $this->generateAccessCode();
DB::update('update events set access_code = ? where id = ?', [$access_code, $eventId]);
// Load updated event from DB.
$event = $this->eventService->api->getEventForce($eventId);
}
// Is the event currently private? return access code
if ($event->privacy=='private') {
return $event->access_code; // HERE: value comes back from the API but on MySQL Workbench it's still null.
}
// Is it public ? return empty string.
else {
return '';
}
}
My problem is that even though everything works as expected. When access_code is created it does come back from the api.
However when I check the record on MySQL Workbench (that connects to AWS Instance) it's still null! event though I pulled it from the database as a non-null value using the API endpoint.
Little confused with your code. From debugging I'd suggest checking your API for this issue. From what I can see you're doing this:
Ask API for event with ID 1
Check if event has a parameter
If no parameter, update using local DB
So I'm left asking, if the problem is with the API, why are you updating using the local instance of the DB? Furthermore could this be resolved using events? (I'm going to call your class something other than event so not to get confusing)
For instance:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Party extends Model {
public $table = 'parties';
public $fillable = [];
public static function boot() {
parent::boot();
static::creating(function($party) {
//create some fancy access code
$access_code = 'heyyyy';
//Check not manually set
if (!isset($party->attributes['access_code']) || is_null($party->attributes['access_code'])) {
$party->access_code = $access_code;
}
}
}
}
Now every time you create an event or 'party' using Party::create(); or $party = new Party; $party->save(); the creating event will pick up the save and also assign the access_code if you haven't set it manually like $party->access_code = 'you can\'t come';.
That's my thought anyway. However in your immediate case I think you need to ask yourself some more questions like:
Does the DB object from the instance of Laravel I'm using have access to the database to save said object?
Do I need to call the API in order to update my entity/model?
If the instance of Laravel I'm using from the \DB::update call have the same credentials as my API?
If this is a command or job, do my code changes affect it? Do I need to restart a supervisor/cron command to re-instance my code?
Who wrote this API? Is it reliable enough to use? And does it have documentation?
I have a Model - Car - the Car has several associated models, lets consider one of them which is linked with the hasMany relationship - Wheel
In my CarsController, I dynamically generate a datasource using the following code -
$schemaName = $this->Session->read('User.schema');
$config = ConnectionManager::getDataSource('default')->config;
$config['database'] = $schemaName;
ConnectionManager::create($schemaName, $config);
Then I set this datasource in my Car Model using the following line of code
$this->Car->setDataSource($schemaName);
After this I am able to query and operate on Car, however, if I try to operate on Wheel using the following statements - I get an error
$this->Car->Wheel->create();
$this->Car->Wheel->save($wheelData);
The error I get is -
Error: [MissingTableException] Table wheels for model Wheel was not found in datasource default.
For some reason the datasource is not being passed from Parent model to associated child models. If I explicitly set the datasource in Wheel using the following line then everything works fine.
$this->Car->Wheel->setDataSource($schemaName);
Can anyone help shed some light on this behavior and how to fix this? The reason I find this inconvenient is that my parent model has several associated models (which further have associated models) and setting datasource individually on each of them doesnt sound right.
Side Question - is there a way to check if a datasource already exists before trying to create one dynamically? I have a for-loop that wraps this entire code and each loop iteration will end up creating a new datasource
I am using CakePHP 2.5.4
Here is some code which will pass the setDatasource() call to associated models, if you want only the Car model to pass through its datasource put this code in the Car model, if you want all models to pass through, put it in AppModel.php
public function setDatasource($datasource = null) {
foreach (array_keys($this->getAssociated()) as $modelName) {
$this->{$modelName}->setDatasource($datasource);
}
parent::setDatasource($datasource);
}
To answer your comment, I would add public $dynamicDb = false in AppModel.php, meaning false would be the default value for this variable, then in your models override it by adding public $dynamicDb = true, then change the above function to:
public function setDatasource($datasource = null) {
foreach (array_keys($this->getAssociated()) as $modelName) {
if ($this->{$modelName}->dynamicDb === true) {
$this->{$modelName}->setDatasource($datasource);
}
}
parent::setDatasource($datasource);
}
(I haven't tested this amended function as I'm not on my dev PC right now, but its a fairly simple change and it should work)
To check if a datasource already exists before you create one, I can see two possible methods, one is by calling ConnectionManager::getDatasource($schemaName) and catching the exception if the datasource does not exist, or call ConnectionManager::sourceList() and check if your $schemaName is in the returned array, here's an implementation of the first option:
$schemaName = $this->Session->read('User.schema');
try {
ConnectionManager::getDatasource($schemaName)
} catch (MissingDatasourceException $e) {
$config = ConnectionManager::getDataSource('default')->config;
$config['database'] = $schemaName;
ConnectionManager::create($schemaName, $config);
}
and the second option:
$datasources = ConnectionManager::sourceList();
$schemaName = $this->Session->read('User.schema');
if (!in_array($schemaName, $datasources)) {
$config = ConnectionManager::getDataSource('default')->config;
$config['database'] = $schemaName;
ConnectionManager::create($schemaName, $config);
}
Hope this helps
In some of my tests, I have a user model I have created and I run some methods that need to save certain attributes. In rails, I would typically call something like user.reload which would repopulate the attributes from the database.
Is there a way in laravel to do that? I read through the api and couldn't find a method for it: http://laravel.com/api/4.1/Illuminate/Database/Eloquent/Model.html Any ideas on the "right" way to do this?
There was a commit submitted to the 4.0 branch made in August to add a reload() method, but so far it hasn't been merged with the newer Laravel branches.
But... Laravel 5 is providing a "fresh()" method that will return a new instance of the current model. Once you're using Laravel 5.0 or newer, you can reload a model like this:
$model = $model->fresh();
Note that fresh() doesn't directly update your existing $model, it just returns a new instance, so that's why we need to use "$model = ". It also accepts a parameter which is an array of relations that you want it to eager load.
If you aren't yet using Laravel 5 but you want the same functionality, you can add this method to your model(s):
public function fresh(array $with = array())
{
$key = $this->getKeyName();
return $this->exists ? static::with($with)->where($key, $this->getKey())->first() : null;
}
Update: If you're using Laravel 5.4.24 or newer, there is now a $model->refresh() method that you can use to refresh the object's attributes and relationships in place rather than fetching a new object like fresh() does. See Jeff Puckett answer for more specifics on that.
Thanks to PR#19174 available since 5.4.24 is the refresh method.
$model->refresh();
This way you don't have to deal with reassignment as is shown in other answers with the fresh method, which is generally not helpful if you want to refresh a model that's been passed into another method because the variable assignment will be out of scope for the calling contexts to use later.
refresh() is a mutable operation: It will reload the current model instance from the database.
fresh() is an immutable operation: It returns a new model instance from the database. It doesn't affect the current instance.
// Database state:
$user=User::create([
'name' => 'John',
]);
// Model (memory) state:
$user->name = 'Sarah';
$user2 = $user->fresh();
// $user->name => 'Sarah';
// $user2->name => 'John'
$user->refresh();
// $user->name => 'John'
I can't see it either. Looks like you'll have to:
$model = $model->find($model->id);
You can also create one yourself:
public function reload()
{
$instance = new static;
$instance = $instance->newQuery()->find($this->{$this->primaryKey});
$this->attributes = $instance->attributes;
$this->original = $instance->original;
}
Just tested it here and it looks it works, not sure how far this goes, though, Eloquen is a pretty big class.
I believe #Antonio' answer is the most correct, but depending on the use case, you could also use a combination of $model->setRawAttributes and $model->getAttributes.
$users = User::all();
foreach($users as $user)
{
$rawAttributes = $user->getAttributes();
// manipulate user as required
// ..
// Once done, return attribute state
$user->setRawAttributes($rawAttributes);
}
The primary downside to this is that you're only "reloading" the data attributes, not any relationships you've altered, etc. That might also be considered the plus side.
EDIT
As of L5 - fresh() is the way to go
How can I construct array of instances of a kind of library (lets say Student) after loading it in CodeIgniter? As far as I know after loading student library using $this->load->library('student'); I can access single student using $this->student . Here is my question, I need an array of this students how can I do that.
You should really use a model instead of a library. Libraries are used to extend the functionality of CodeIgniter. Models let you interact with your data; Students in this case. Using a library to get your data and instantiating it is shooting yourself in the foot.
In your Student_model, you can put functions that grab your data (from a database or wherever):
function get_students() {
// Returns an array or object of all students and their info
}
function get($student_id) {
// Returns a single student's information
}
// Additional CRUD functions, if desired.
Additionally, I recommend having another look at:
http://ellislab.com/codeigniter/user-guide/overview/mvc.html
http://ellislab.com/codeigniter/user-guide/general/creating_libraries.html
inside your library file
function get_student_list()
{
// $uqery = SQL query to get the students - or a call to your model to get them
return $query;
}
then in your controller
$list = $this->student->get_student_list();