Unexpected data found during update on eloquent / Laravel - postgresql

I am using ajax to update a model that contains timestamps, but it throw me an exception:
{message: "Unexpected data found.", exception: "InvalidArgumentException",…}
message: "Unexpected data found."
exception: "InvalidArgumentException"
file: "/home/asus/Devagnos/almada/vendor/nesbot/carbon/src/Carbon/Traits/Creator.php"
line: 623
trace: [,…]
i have disabled the timestamps and i set the dateformat like this:
protected $dateFormat = 'Y-m-d H:i:s.u';
public $timestamps = false;
protected $dates = [
'created_at',
'updated_at'
];
alse I added these methods
/**
* #param $val
*/
public function setCreatedAtAttribute($val)
{
return Carbon::createFromFormat('Y-m-d H:i:s.u', $val);
}
/**
* #param $val
*/
public function setUpdatedAtAttribute($val)
{
return Carbon::createFromFormat('Y-m-d H:i:s.u', $val);
}
but I am always getting the same error, What am I doing wrong ?
I'm using laravel 6.8 and postgresql

If you're trying to use microseconds, then you should refer to this guide from the documentation:
https://carbon.nesbot.com/laravel/
I don't get what you tried with setCreatedAtAttribute and setUpdatedAtAttribute, setters are supposed to change the inner property, not to return a value.
Then check you gave to your DB columns enough precision (such as TIMESTAMP(6)) in your migration schemas.

Related

SuiteCRM v7.10.29 Custom API v4.1

I am creating a custom API for SuiteCRM. When I attempt to run the new API from {CRM Home}/custom/service/v4_1_custom I receive an 'HTTP ERROR 500'. There are not errors in the error_log file or the SuiteCRM.log file.
I have followed the method in the following two url's
https://fayebsg.com/2013/05/extending-the-sugarcrm-api-updating-dropdowns/
https://support.sugarcrm.com/Documentation/Sugar_Developer/Sugar_Developer_Guide_10.0/Integration/Web_Services/Legacy_API/Extending_Web_Services/
registry.php
<?php
require_once('service/v4_1/registry.php');
class registry_v4_1_custom extends registry_v4_1
{
protected function registerFunction()
{
parent::registerFunction();
$this->serviceClass->registerFunction('test', array(), array());
}
}
SugarWebServicesImplv4_1_custom.php
<?php
if(!defined('sugarEntry'))define('sugarEntry', true);
require_once('service/v4_1/SugarWebServiceImplv4_1.php');
class SugarWebServiceImplv4_1_custom extends SugarWebServiceImplv4_1
{
/**
* #return string
*/
public function test()
{
LoggerManager::getLogger()->warn('SugerWebServiceImplv4_1_custom test()');
return ("Test Worked");
} // test
} // SugarWebServiceImplv4_1_custom
I found the answer to this issue.
In the file {SuiteCRM}/include/entryPoint.php there are many files that are included thru require_once. In this list of require_once files, there were 4 files that were set as require not require_once. These were classes and therefore could not be included a second time. I changed these to require_once and the HTTP Error 500 went away and the custom APIs started working.

Symfony 4 + Api platform Cannot validate values of type \"NULL\" automatically. on nativeSQL query

i have been stuck for few hours with this:
Doing a simple query on my Variation base :
$query = "UPDATE variation SET status = 'FALSE' WHERE id IN
('ba21ac3f-0e7f-4bb9-b31f-dbd49053002e','a656e102-0339-4db0-a4b1-16451c2f1d90','64da7d32-2c9f-4478-bc6d-0b7b6c07af8e','8aba2925-7017-4899-bdfa-bf341c0fccec','6d4374cb-3713-4162-be53-2232202b5809','1810057a-6157-45bf-85d5-ade282b7d807','967d7495-6e93-4530-b6d8-d23640b39226','ebdcd88f-1f58-44b6-a14d-d0db9a564671')";
$result = $this->entityManager->getConnection()->prepare($query);
$result->execute();
And using postman it's returning me :
"#context": "/contexts/Error",
"#type": "hydra:Error",
"hydra:title": "An error occurred",
"hydra:description": "Cannot validate values of type \"NULL\" automatically. Please provide a constraint."`
my variation class:
/**
* #var bool
*
* #ORM\Column(type="boolean")
*
* #Groups({"variation"})
*/
protected $status;
How comes it try to validate somethings. Ps the query is fully working ( POSTGRES - Symfony 4.2 - PHP72 )
If body content is empty in request, its possible to correct that if content type are is also empty in header request

How to write Monolog logs into a file AND remote database

I have a Symfony2 -project and it writes the logs into different files beautifully, but I would like it to write the logs into a remote database(mongodb) as well. I would like to keep the actual log files in the servers as a backup in case something goes wrong with the database connection.
Question 1:
Is it even possible to save the same logs into two different places at the same time?
Question 2:
How do I save the logs into the mongodb? I don't necessarily need specific mongodb-instructions, but some guidelines on how to write into a remote db with monologger. The mongodb-specific instructions are also welcome if available. ;)
Question 3(OPTIONAL):
Can I get a full error stack into the logs somehow? Where could one find a full list of what data the Monolog can actually write and how to write?
There was a very good Blogpost sometime back for logging to a mysql database with monolog and doctrine. I can't find it anymore so i will just add the neccessary Files here and you can adjust it.
The whole logic is done in the DatabaseHandler so you can just change from
mysql inserts to a handling for your mongodb.
This code is not mine if anyone knows the original post please comment.
BacktraceLoggerListener.php
namespace UtilsBundle\EventListener;
use Symfony\Component\HttpKernel\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
class BacktraceLoggerListener{
private $_logger;
public function __construct(LoggerInterface $logger = null)
{
$this->_logger = $logger;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$this->_logger->addError($event->getException());
}
}
DatabaseHandler.php
namespace UtilsBundle\Logger;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Logger;
/**
* Stores to database
*
*/
class DatabaseHandler extends AbstractProcessingHandler{
protected $_container;
/**
* #param string $stream
* #param integer $level The minimum logging level at which this handler will be triggered
* #param Boolean $bubble Whether the messages that are handled can bubble up the stack or not
*/
public function __construct($level = Logger::DEBUG, $bubble = true)
{
parent::__construct($level, $bubble);
}
/**
*
* #param type $container
*/
public function setContainer($container)
{
$this->_container = $container;
}
/**
* {#inheritdoc}
*/
protected function write(array $record)
{
// Ensure the doctrine channel is ignored (unless its greater than a warning error), otherwise you will create an infinite loop, as doctrine like to log.. a lot..
if( 'doctrine' == $record['channel'] ) {
if( (int)$record['level'] >= Logger::WARNING ) {
error_log($record['message']);
}
return;
}
// Only log errors greater than a warning
// TODO - you could ideally add this into configuration variable
if( (int)$record['level'] >= Logger::NOTICE ) {
try
{
// Logs are inserted as separate SQL statements, separate to the current transactions that may exist within the entity manager.
$em = $this->_container->get('doctrine')->getManager();
$conn = $em->getConnection();
$created = date('Y-m-d H:i:s');
$serverData = ""; //$record['extra']['server_data'];
$referer = "";
if (isset($_SERVER['HTTP_REFERER'])){
$referer= $_SERVER['HTTP_REFERER'];
}
$stmt = $em->getConnection()->prepare('INSERT INTO system_log(log, level, server_data, modified, created)
VALUES(' . $conn->quote($record['message']) . ', \'' . $record['level'] . '\', ' . $conn->quote($referer) . ', \'' . $created . '\', \'' . $created . '\');');
$stmt->execute();
} catch( \Exception $e ) {
// Fallback to just writing to php error logs if something really bad happens
error_log($record['message']);
error_log($e->getMessage());
}
}
}
}
We used xml here but this can be done in
services.yml too
services.xml
<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="utils.database.logger" class="UtilsBundle\Logger\DatabaseHandler">
<call method="setContainer">
<argument type="service" id="service_container" />
</call>
</service>
<service id="utils.backtrace.logger.listener" class="UtilsBundle\EventListener\BacktraceLoggerListener">
<argument type="service" id="logger" />
<tag name="monolog.logger" channel="backtrace" />
<tag name="kernel.event_listener" event="kernel.exception" method="onKernelException" />
</service>
</services>
And lastly add the handler to your monolog config in
config_**.yml so here for production for example
config_prod.yml
monolog:
handlers:
main:
type: rotating_file
action_level: error
max_files: 10
handler: nested
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
console:
type: console
database:
type: service
level: notice
id: utils.database.logger
channels: ["!translation"]
Hope that helps
Hope I can some things up for you:
Question 1: Yes its possible. E.G. you can do smt. like:
$this->logger->pushHandler(new StreamHandler('/path/to/logs/123_info.log', Logger::INFO));
$this->logger->pushHandler(new StreamHandler('/path/to/logs/456_warning.log', Logger::INFO));
So if $this->logger->addInfo("testinfo"); this is getting logged in both streams.
Question 2: There is a MongoDBHandler as according to the StreamHandler. You should be able do configure it and pass it along to the pushHandler method or if you want to have it in your services look at MongoDBConfiguration.
Question 3:
This should help: Configure Monolog
Hope that helps.

doctrine migrations bundle and postgres schema: diff does not work properly

I'm using doctrine in my Symfony project, by connecting to an already existent postgres database.
The DB has several schemas, but the symfony app will use nothing but its own schema. The first Entity class I created is the following one:
namespace Belka\TestBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity
* #ORM\Table(name="app_auth.User", schema="app_auth")
*/
class User {
/**
* #ORM\Column(type="string")
* #ORM\Id
* #ORM\GeneratedValue(strategy="NONE")
*/
private $username;
/**
* #ORM\Column(type="string")
*/
private $email;
/**
* #ORM\Column(type="string")
*/
private $password;
}
as you can see, the Entity is specifying its own schema app_auth.
Next, I tried to use the migrations bundle. So, I installed and configured it, in order not to consider anything but my schema:
Extract of config.yml:
doctrine:
dbal:
driver: "%database_driver%"
host: "%database_host%"
port: "%database_port%"
dbname: "%database_name%"
user: "%database_user%"
password: "%database_password%"
charset: UTF8
schema_filter: ~^app_auth\..*~
Extract of config_dev.yml:
doctrine_migrations:
dir_name: "%kernel.root_dir%/../.container/update/DoctrineMigrations"
namespace: Application\Migrations
table_name: "app_auth.migration_versions"
name: Application Migrations
And I run the diff:
php app/console doctrine:migrations:diff
Unfortunately, the migration class generated is the following one:
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20160422171409 extends AbstractMigration
{
/**
* #param Schema $schema
*/
public function up(Schema $schema)
{
// this up() migration is auto-generated, please modify it to your needs
}
/**
* #param Schema $schema
*/
public function down(Schema $schema)
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('CREATE SCHEMA app_auth');
}
}
what's wrong with my configuration then?
Dirty but working solution:
Tested with doctrine/migrations: 3.0.1
We can patch out the schema removing functionality of the DiffGenerator. I personally used this https://github.com/cweagans/composer-patches
Install the package, and then in composer.json "extra" section add:
"patches": {
"doctrine/migrations": {
"Change doctrine behavior to correctly pass PostgreSQL schema to schema_filter while diffing": "patches/doctrine-diff-generator.patch"
}
}
The patch file in patches/doctrine-diff-generator.patch:
--- lib/Doctrine/Migrations/Generator/DiffGenerator.php 2020-06-21 10:55:42.000000000 +0200
+++ lib/Doctrine/Migrations/Generator/DiffGenerator.patched.php 2020-12-23 12:33:02.689405221 +0100
## -142,8 +142,6 ##
*/
private function resolveTableName(string $name) : string
{
- $pos = strpos($name, '.');
-
- return $pos === false ? $name : substr($name, $pos + 1);
+ return $name;
}
}
Of course you have to bare in mind, that updates to doctrine could break the patch. And you are changing this functionality globally for your doctrine, so beware of breaking changes.
Personally, for my use case, which is adding doctrine entities into legacy database, without breaking it, this works nicely, and saves me from adding every new table managed by doctrine into the schema_filter.
Explanation:
When we look into DiffGenerator implementation it actually decodes the table names with schema correctly, but only when collecting the current database schema. This happens in PostgreSqlSchemaManager.php:
/**
* {#inheritdoc}
*/
protected function _getPortableTableDefinition($table)
{
$schemas = $this->getExistingSchemaSearchPaths();
$firstSchema = array_shift($schemas);
if ($table['schema_name'] === $firstSchema) {
return $table['table_name'];
}
return $table['schema_name'] . '.' . $table['table_name'];
}
But then then when calculating the target schema, this information is lost here in DiffGenerator.php:
/**
* Resolve a table name from its fully qualified name. The `$name` argument
* comes from Doctrine\DBAL\Schema\Table#getName which can sometimes return
* a namespaced name with the form `{namespace}.{tableName}`. This extracts
* the table name from that.
*/
private function resolveTableName(string $name) : string
{
$pos = strpos($name, '.');
return $pos === false ? $name : substr($name, $pos + 1);
}
And only afterwards the return value of this function is passed into the schema_filter. Unfortunate, but i guess there was a reason for this :)

Unit Testing with PHPUnit & Doctrine2: Autoloading Failed

I am getting this error
D:\Projects\Tickle\tests>phpunit
PHPUnit 3.5.5 by Sebastian Bergmann.
..........ok1
Fatal error: Doctrine\Common\ClassLoader::loadClass(): Failed opening required 'D:\Projects\Tickle\Application\Models\Ap
plication\Models\User.php' (include_path='D:\Projects\Tickle\application/../library;D:\Projects\Tickle\application;D:\Pr
ojects\Tickle\library;D:\ResourceLibrary\Frameworks\PHPFrameworks;C:\Program Files (x86)\PHP\pear;.;c:\php\includes') in
D:\ResourceLibrary\Frameworks\PHPFrameworks\Doctrine\Common\ClassLoader.php on line 148
Notice its repetition "D:\Projects\Tickle\Application\Models\Application\Models\User.php" of Application\Models. I narrowed it down to 1 function of my unit tests with the help of some echo statements
protected function isAllowed($userId, $taskId, $privilege) {
$user = $this->em->find('Application\Models\User', $userId);
echo 'ok1'; // this gets printed
$task = $this->em->find('Application\Models\Task', $taskId); // this seem to be the cause of the problem
echo 'ok2'; // this doesn't get printed
return $this->acl->isAllowed($user, $task, $privilege);
}
The full class http://pastebin.com/rJungFvP
So I tried looking of something in the Tasks class that uses User ... the only thing that might use the User class are
/**
* #ManyToOne(targetEntity="User", inversedBy="ownedTasks")
*/
protected $owner;
/**
* #ManyToOne(targetEntity="User", inversedBy="assignedTasks")
*/
protected $assigned;
apart from that, I don't see use of any Users. full class http://pastebin.com/wDPXUPSV.
What did I do wrong?
The problem was actually found in the TodoList class ... I had something like
public function setProject(Application\Models\Project $project) {
...
}
when I should be using something like
public function setProject(Project $project) {
$this->project = $project;
}
instead