I am customizing the SugarCRM. At some point I need to store some custom values to the database while user creates the record. I tried to use Triggers, but it didn't fulfill the requirement. So I need to write that in PHP code.
My question is, where to write this code.
Use logic hooks (after_save or before_save e.g.) on the module's save action.
Create a logic_hooks.php in custom/modules/myModule/
<?
$hook_array = Array();
$hook_array['after_save'] = Array();
$hook_array['after_save'][] = Array(
0,
'myName',
'custom/modules/myModule/logic_hooks/file.php',
'myClass',
'myMethod'
);
?>
Create file.php in /custom/modules/myModule/logic_hooks/
<?php
class myClass{
function myMethod(&$bean, $event, $arguments){
// Do something with $bean (e.g. store the custom DB value)
}
}
?>
For more info see: this link.
Make sure that your_php_file.php is executable by apache. It could be that or possibly a misspelling? See if there is anything in your apache log files.
Related
I'm a noob junior so I apologise in advance if this is a very basic question and if it has been asked a gazillion times before.
I am basically trying to run another function when a user registers. After some googling I came upon: hook_entity_insert($entity, $type) from (https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_entity_insert/7.x) now, even though there are code examples it does not tell me where to put the code, how to get the data that is submitted etc...
Which file do I put the sample code to test. The sample code provided is:
function hook_entity_insert($entity, $type) {
// Insert the new entity into a fictional table of all entities.
$info = entity_get_info($type);
list($id) = entity_extract_ids($type, $entity);
db_insert('example_entity')
->fields(array(
'type' => $type,
'id' => $id,
'created' => REQUEST_TIME,
'updated' => REQUEST_TIME,
))
->execute();
}
First you should understand the hook system in Drupal. For Drupal 7 this page is a good start. It gives you a quick overview and understanding of the concept.
Understanding the hook system for Drupal modules
There is a specific hook that 'fires' after an user is inserted, named hook_user_insert
You don't need to use hook_entity_insert. In your custom module use below hook
when user registers.
function yourModuleName_form_user_register_alter(&$form, &$form_state) {
// Add your own function to the array of validation callbacks
$form['#validate'][] = 'yourModuleName_user_register_validate';
}
Refer
Hook into Drupal registration and validate user info against business logic
If you want to run a function after the user has registered, use hook_user_insert (or, if this needs to be run every time a user is changed, hook_user_presave).
In general: Hooks in drupal are functions that comply with a specific naming scheme. In the places where a hook is executed (i.e., on user registration), Drupal searches for all modules that contain a function where the function name consists of the module's (machine) name, followed by the hook name. For hook user insert, you would need to implement a module (or place your code in a module you already implemented), see documentation here. Supposing your module is called "custom_module", you then implement a function like so:
function custom_module_user_insert(&$edit, $account, $category) {
//Do what you wanted to do here
}
Hope this helps
I'm using a package within my project and it stores a setting inside config/packagename
I would like to dynamically change this value inside the config file, this is how the file structure looks currently;
<?php
return [
'view_id' => '118754561',
'cache_lifetime_in_minutes' => 60 * 24,
];
I would like to change it to something like this -
'view_id' => Auth::user()->id,
Can you do this within the config file, or do you have to store some sort of variable to be updated later within a controller. Is there a way to place these variables in an env file and access these new variables from a controller?
This also is a generic solution to dynamically update your .env file (respective the individual key/value pairs)
Change the setting in your config/packagename like so:
return [
'view_id' => env('VIEW_ID', '118754561'),
etc...
]
Add an initial value into .env:
VIEW_ID=118754561
In an appropriate controller (e.g. AuthController), use the code below and call the function like this:
updateDotEnv('VIEW_ID', Auth::User()->id)
protected function updateDotEnv($key, $newValue, $delim='')
{
$path = base_path('.env');
// get old value from current env
$oldValue = env($key);
// was there any change?
if ($oldValue === $newValue) {
return;
}
// rewrite file content with changed data
if (file_exists($path)) {
// replace current value with new value
file_put_contents(
$path, str_replace(
$key.'='.$delim.$oldValue.$delim,
$key.'='.$delim.$newValue.$delim,
file_get_contents($path)
)
);
}
}
(The $delim parameter is needed if you want to make this function more generic in order to work with key=value pairs in .env where the value has to be enclosed in double quotes because they contain spaces).
Admittedly, this might not be a good solution if you have multiple users at the same time using this package in your project. So it depends on what you are using this package for.
NB: You need to make the function public of course if you plan to use it from other classes.
All configuration files of Laravel framework stored in the app/config directory.
so if we need to create custom configuration values it would be better to keep separate our custom configuration in custom file.
so we need to create custom file in app/config directory.
Laravel auto read this file as a config file and will auto manage it
In this topic we are working with custom configuration in laravel and get configuration value in controller or view.
Now i am going to explain how to create a custom config file in Laravel so that we can implement dynamic feature over to this.
create a file in app/config/custom.php which have config keys and value like:-
return array(
'my_val' => 'mysinglelue',
'my_arr_val' => array('1', '2', '3'),
);
Now need to get these config values in view/controller so we will use Config class get() method for this
Syntax:
echo Config::get('filename.arraykey');
where filename is the config file’s name, custom in our case, and key is the array key of the value you’re wanting to access.
In Our case it will be as:
echo Config::get('custom.my_val');
Create run time configuration in laravel :-
Configuration values which are set at run-time are will set for the current request, not be carried over to subsequent requests.
You can pass the dynamic values over here so that you can modify the config file dynamically over here using the isset() functions.
Like how the #Kundan roy as suggested using of the isset() the same condition applies here to. But this one is the alternative method that will work for the dynamic setting of the values in the config.
Config::set('custom.my_val', 'mysinglelue');
Hence by using this method you can create the dynamic config files based on the values that you need.
Since Laravel v5.2 you can dynamically set config values this way:
<?php
config(['app.timezone' => 'America/Chicago']);
$value = config('app.timezone');
echo $value;
// output: 'America/Chicago'
If you want to actually edit the config files (either config/packagename.php or .env) then you may follow matthiku's answer.
However, if I were you, I guess I'd rather want to configure this 3rd party package based on some value defined at runtime, instead of modifying any file (which by the way won't take effect until the next request, when the env values are read again).
So, in my opinion the cleanest way to do this is:
store your desired value in the config data:
config(['packagename.view_id' => Auth::user()->id]);
However, you may notice this probably won't work: the service provider which provides the service you need is often registered before the request is processed, that is, before your config change takes place. So you are still getting the service with old values config.
So, how could you have the service provider be called only when needed and not before (that is, after setting the new config value)? You could make it a deferred provider. Following your example of "spatie laravel-analytics", replace in config/app.php this line:
Spatie\Analytics\AnalyticsServiceProvider::class
with this one:
App\Providers\AnalyticsDeferredServiceProvider::class
and finally create the App\Providers\AnalyticsDeferredServiceProvider class, with:
:
<?php
namespace App\Providers;
use Spatie\Analytics\Analytics;
use Spatie\Analytics\AnalyticsServiceProvider;
class AnalyticsDeferredServiceProvider extends AnalyticsServiceProvider
{
protected $defer = true;
public function provides()
{
return [Analytics::class];
}
}
This way you can have the provider read the config values when you are about to instantiate the service, after you set any runtime config values.
Use this in controller when you need to change.
<?php
use Illuminate\Support\Facades\Config;
//[...]
$user_id = Auth::user()->id;
Config::set('view_id', $user_id );
You can do like this.
In your custom config file. Add the following code You can send your id dynamically from the query string.
'view_id' => isset($_REQUEST['view_id'])?$_REQUEST['view_id']:null,
To get view id
echo config('app.view_id'); // app is config file name
config(['packagename.view_id' => Auth::user()->id]);
Actually if you are that point of code which forces you to make the config values dynamic, then there should be something wrong with your code flow, as the use of config file is just for initializing required values - which should be defined before the app is loaded.
Making config values dynamic is a "BAD PRACTICE" in the world of coding.
So there is the following alternative for your problem.
Define value in .env file (optional)
VIEW_ID=your_view_id_here
Use value inside Controller
$auth_id = auth()->user()->id;
$view_id = env('VIEW_ID', $auth_id);
// If .env file doesn't contains 'VIEW_ID' it will take $auth_user as the view_id
Hope this helps you!
config::set() doesn't works for me in laravel 8. but I got best answer for Create or edit Config file
config(['YOUR-CONFIG.YOUR_KEY' => 'NEW_VALUE']);
$text = '<?php return ' . var_export(config('YOUR-CONFIG'), true) . ';';
file_put_contents(config_path('YOUR-CONFIG.php'), $text);
just try this way this works for me.
original answer you can see here
for example, i have "config.php":
<?php
class Config {
public $var1 = 'ex1';
public $var2 = 'ex2';
}
?>
and i have "index.php"
<?php
include ('config.php');
$a = new Config();
$a->var1='changed_ex1';
$a->var2='changed_ex2';
UPDATE($a,'config.php');
?>
so here is the question - what shoud be in UPDATE function to write changes into config.php?=)
I highly do not recommend writing files to store configuration. I'd rather store config in the database if I need to change the settings during runtime.
But if you insist on your chosen path, your UPDATE function will need to read the entire file and either regex-replace the necessary keys, or simply re-render the entire thing based on stored data and the data you need to change.
Hey guys, I've used the Symfony admin generator for a module.
Everything is working, but when the form for my model is instantiated, I need to pass in my own option.
I could do this myself by overriding the executeNew, executeCreate functions in myModuleActions.class.php (which extends myModuleAutoActions).
But I was hoping for a neater solution?
Perhaps overriding one of the configuration classes is the way to go. I basically need to add the current sf_user object ($this->getUser) as an "sf_user" option for the form, to avoid using sfContext in the myModuleForm.
Any ideas?
Welcome to Stack Overflow, jolly18.
I would just use sfContext. For example, in my app, I have a subform that creates a new Note object and assigns the user to it. In my form's configure() I have:
$new_note->setAuthor(sfContext::getInstance()->getUser()->getUsername());
I see the book calls this "The fastest but ugly way" because it makes "a big coupling between the form and the context, making the testing and reusability more difficult." But in practice... this works well and I can move on.
if module was generated using admin-generator :
in apps/backend/modules/books/actions/actions.class.php
modify: in
executeEdit(){
//leave rest unchanged
$values=array('activity_id'=>$activity_id, 'book_id'=>$book_id, 'todo_id'=>$todo_id, 'user_id'=>$this->getUser()->getGuardUser()->getId());
$this->form = new TabelBooksForm($TabelBooks, $values);
}
modify: in
executeNew(){
//leave rest unchanged
$values=array('activity_id'=>$activity_id, 'book_id'=>$book_id, 'todo_id'=>$todo_id, 'user_id'=>$this->getUser()->getGuardUser()->getId());
$this->form = new TabelBooksForm(array(), $values);
}
in TabelBooksForm.class.php
public function configure()
{
if ($this->isNew()) {
$this->setWidget('book_id', new sfWidgetFormInputHidden());
$this->setDefault('book_id', $this->getOption('book_id'));
$this->setWidget('activity_id', new sfWidgetFormInputHidden());
$this->setDefault('activity_id', $this->getOption('activity_id'));
$this->setWidget('todo_id', new sfWidgetFormInputHidden());
$this->setDefault('todo_id', $this->getOption('todo_id'));
}
}
i've been facing this problem for a while but symfony always surprises me with some neat code that i was not aware of.
I assume you'r using sfPropelPlugin, quite standar, if you checkout the code generated in cache (note: this code will be available once you tried to open the module from the browser, so firts try to look at it so we dont get in trouble :P) you may see something like:
cache/{application_name}(generally frontend or backend)/dev(enviromnemt)/autoModule_name( look here for the module)/:
lib
action
The action folder contains an action.class.php file that defines all actions generated by the generator (executeNew, Edit, Create, Update, etc). If you look a the implementation of executeNew and executeEdit, you can see that they ask a configuration instace the actual form to display, here is an example:
public function executeNew(sfWebRequest $request)
{
$this->form = $this->configuration->getForm();
$this->PaymentOrder = $this->form->getObject();
}
The configuration var containt an instance of a configuration class defined in the lib folder i mentioned earlier. That class tweaks the form to fit the object needs (generally by setting a fresh object instance).
So here comes the magic, the classes you see in your module extend from those in cache, so by pure logic, if you modifi the getForm() method in the main module/lib folder to fit your needs, you wont have to hack forms by getting user valuer where you shouldn't.
Hope this helps!
I was thinking about implementing a logic similar to observer pattern on my website, for implementing hooks.
What I am looking for is something similar to this Best way to allow plugins for a PHP application
However the code there is too limited, as I cant attach multiple hooks to same listener.
I am clueless about how to amplify that code to make it able to listen multiple actions at one event.
Thank You
You can do as ircmaxell suggests: add hooks. But clearly, the information he gave was not enough for you.
If you like learning by example, you may look at the CMS Drupal, wich is not OOP, but uses the observer pattern, called hooks all over the place to allow a modular design.
A hook works as follows:
a piece of php looks for the existence of a specially named function.
If that exists, call it and use its output (or do nothing with it)
For example:
Just before an article gets saved in Drupal, the article-system calls the hook_insert
Every module that has a function in the name of ModuleName_insert, will see that function being called. Example: pirate.module may have a function pirate_insert(). The article system makes a roundtrip along all the modules and sees if ModuleName_insert exists. It will pass by pirate module and finds pirate_insert(). It will then call that function (and pass some arguments along too). As such, allowing the pirate.module to change the article just before insertation (or fire some actions, such as turning the body-text into pirate-speek).
The magic happens in so called user_callbacks. An example:
$hook = 'insert'
foreach (module_implements($hook) as $module) {
$function = $module .'_'. $hook;
$result = call_user_func_array($function, $args);
}
And the function module_implements might look something like:
$list = module_list(FALSE, TRUE, $sort); //looks for files that are considered "modules" or "addons".
foreach ($list as $module) {
if (function_exists($module.'_'.$hook)) { //see if the module has the hook 'registered'
$implementations[$hook][] = $module; //if so: add it to a list with functions to be called.
}
}
Simply add a ' * ' hook, and modify the hook() function to call all the 'hooks' in both the named event and the ' * ' event.
Then, simply do:
add_listener('*', 'mycallback');
Take a look at Spl_Observer.
You said you didn't want OOP, but you can easily implement a non-OOP wrapper around this.