How do I let users set the database configuration for a new CI install?
My intention is to have a form that allows them to enter the data then either generate a new config file or to set the options in the database.php file.
Is this possible?
Let's say you want to create a database config file. Here's how I do it:
Create a "dummy" config file by copying a real one, and use values that look something like this:
$db['default']['hostname'] = '__HOSTNAME__';
$db['default']['username'] = '__USERNAME__';
$db['default']['password'] = '__PASSWORD__';
$db['default']['database'] = '__DATABASE__';
Have the user complete the installation form, and verify all the data by testing a database connection. Next, use file_get_contents() to grab the content of the "dummy" config file, use a simple str_replace() to rewrite the values with the ones the user provided, then write the new content to your real config file overwriting the entire thing.
Here's part of the actual code I'm using for creating the file, just to get an idea. Bear in mind that I'm running this on a totally separate CI installation (the "installer"), and this is not a copy/paste example:
// Write the database configuration file
$config = array(
'hostname',
'username',
'password',
'database',
);
$data = file_get_contents(APPPATH.'config/dummy_database.php');
$file = '../private/config/database.php';
// Oops! Just caught this after posting: str_replace() accepts arrays.
// TODO: Use the array method instead of a loop!
foreach ($config as $item)
{
$data = str_replace('____'.strtoupper($item).'____', mysql_escape_string($this->data[$item]), $data);
}
if (write_file($file, $data))
{
$this->message('Database configuration file was written!', 'success');
#chmod($file, 0644);
{
if (is_really_writable($file))
{
$this->message('The database configuration is still writable, make sure to set permissions to <code>0644</code>!', 'notice');
}
}
}
else
{
$this->message('Could not write the database configuration file!');
redirect('step_4');
}
This retains the original copy of the "dummy" config file. You could use the same logic for editing, just read the current config values for anything the user has not changed and do the same string replacement technique.
Related
I am working on Laravel. I have questions about update / add configuration dynamically. Let me tell you my question.
I am updating / add the global configuration of my project using the file_put_content in config file. I have another way, save configuration into the database and pull that configuration at the time of login to the system.
Which way is better to use and why?
one way is maintain seprate table for config data if your data is static means nothing have to change in that data. and then create provider to get your data and bind that data at run time
public function boot()
{
if (Schema::hasTable('roles')) {
$roles = Role::pluck('name', 'id')->all();
$data = collect($roles)->mapWithKeys(function ($item, $index) {
return [str_slug($item, '_') => $index];
})->all();
config(['configfilename.configkey' => $data]);
}
}
Like this you can get your config data at run time
I am allowing users to upload any kind of file on my page, but there might be a clash in names of files. So, I want to rename the file automatically, so that anytime any file gets uploaded, in the database and in the folder after upload, the name of the file gets changed also when other user downloads the same file, renamed file will get downloaded.
I tried:
if (Input::hasFile('file')){
echo "Uploaded</br>";
$file = Input::file('file');
$file ->move('uploads');
$fileName = Input::get('rename_to');
}
But, the name gets changed to something like:
php5DEB.php
phpCFEC.php
What can I do to maintain the file in the same type and format and just change its name?
I also want to know how can I show the recently uploaded file on the page and make other users download it??
For unique file Name saving
In 5.3 (best for me because use md5_file hashname in Illuminate\Http\UploadedFile):
public function saveFile(Request $request) {
$file = $request->file('your_input_name')->store('your_path','your_disk');
}
In 5.4 (use not unique Str::random(40) hashname in Illuminate\Http\UploadedFile). I Use this code to ensure unique name:
public function saveFile(Request $request) {
$md5Name = md5_file($request->file('your_input_name')->getRealPath());
$guessExtension = $request->file('your_input_name')->guessExtension();
$file = $request->file('your_input_name')->storeAs('your_path', $md5Name.'.'.$guessExtension ,'your_disk');
}
Use this one
$file->move($destinationPath, $fileName);
You can use php core function rename(oldname,newName) http://php.net/manual/en/function.rename.php
Find this tutorial helpful.
file uploads 101
Everything you need to know about file upload is there.
-- Edit --
I modified my answer as below after valuable input from #cpburnz and #Moinuddin Quadri. Thanks guys.
First your storage driver should look like this in /your-app/config/filesystems.php
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'), // hence /your-app/storage/app/public
'visibility' => 'public',
],
You can use other file drivers like s3 but for my example I'm working on local driver.
In your Controller you do the following.
$file = request()->file('file'); // Get the file from request
$yourModel->create([
'file' => $file->store('my_files', 'public'),
]);
Your file get uploaded to /your-app/storage/app/public/my_files/ and you can access the uploaded file like
asset('storage/'.$yourModel->image)
Make sure you do
php artisan storage:link
to generate a simlink in your /your-app/public/ that points to /your-app/storage/app/public so you could access your files publicly. More info on filesystem - the public disk.
By this approach you could persists the same file name as that is uploaded. And the great thing is Laravel generates an unique name for the file so there could be no duplicates.
To answer the second part of your question that is to show recently uploaded files, as you persist a reference for the file in the database, you could access them by your database record and make it ->orderBy('id', 'DESC');. You could use whatever your logic is and order by descending order.
You can rename your uploaded file as you want . you can use either move or storeAs method with appropiate param.
$destinationPath = 'uploads';
$file = $request->file('product_image');
foreach($file as $singleFile){
$original_name = strtolower(trim($singleFile->getClientOriginalName()));
$file_name = time().rand(100,999).$original_name;
// use one of following
// $singleFile->move($destinationPath,$file_name); public folder
// $singleFile->storeAs('product',$file_name); storage folder
$fileArray[] = $file_name;
}
print_r($fileArray);
correct usage.
$fileName = Input::get('rename_to');
Input::file('photo')->move($destinationPath, $fileName);
at the top after namespace
use Storage;
Just do something like this ....
// read files
$excel = $request->file('file');
// rename file
$excelName = time().$excel->getClientOriginalName();
// rename to anything
$excelName = substr($excelName, strpos($excelName, '.c'));
$excelName = 'Catss_NSE_'.date("M_D_Y_h:i_a_").$excelName;
$excel->move(public_path('equities'),$excelName);
This guy collect the extension only:
$excelName = substr($excelName, strpos($excelName, '.c'));
This guy rename its:
$excelName = 'Catss_NSE_'.date("M_D_Y_h:i_a_").$excelName;
I'm setting up a system configuration in the admin backend of magento, and it currently stores it the data in a file, and I wanted to have Magento grab the data from a file to show what the current value is. What method should I be overloading to achieve this? I thought it was the load() function after extending Mage_Core_Model_Config_Data, but that was wrong.
In order to set the System Configuration Data for your admin, you can try writing upgrade-scripts in your local module in the sql folder. Below is one example where I have set up the System Config Value for Avalanche.
<?php
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
$setup->startSetup();
$setup->setConfigData('avalanche_config/avalanche_design/avalanche_customcss','1');
$setup->endSetup();
Syntax and Usage of setConfig data
***setConfigData***
access: public
void setConfigData ( $path, $value, [ $scope = 'default'], [ $scopeId = 0], [ $inherit = 0])
$path
$value
$scope
$scopeId
$inherit
You can refer to http://codemagento.com/2011/02/install-scripts-and-upgrade-scripts/ for writing upgrade scripts.
This is one of the solution of setting up the System Config data, I am not sure if this works for you.
Anyway, good luck.
Swapna
In my app I have a module named "client". I wish to create a sub directory "statements" and below that "accounts" then "account_123" and within this directory the pdfs representing statements for clint 123.
Structure client then statements then accounts then acount_XXX and the pdf files.
The problem
statement_1.pdf?
Being MVC I am making little progess.
I moved the structure to public and it almost wotk except I could not retrieve dynamically the hostname i.r. www.hostnam.com/client/statement....
I know this is a security issue so I have moved the directory back yo below the client module.
Any help will be appreciayed.
TIA Ephraim
As far as I know you can't place a direct link to a file placed under 'application' director (because of security issues as you already wrote), so one of possible solution is to make an action which read the content of a file and return it in a response object.
When user click a link to this action user get a window to open/save provided file.
Example:
public function exampleAction() {
$this->_helper->layout->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
/* ... */
$file = "FILENAME WITH_PATH";
$response = $this->getResponse();
$response->setHeader('Cache-Control', 'public', true);
$response->setHeader('Content-Description', 'public', true);
$response->setHeader('Content-Disposition', 'attachment; filename=' . FILENAME, true);
$response->setHeader('Content-Type', FILETYPE, true);
$response->setHeader('Content-Transfer-Encoding', 'binary', true);
$response->setHeader('Content-Length', filesize($file), true);
$response->setBody(file_get_contents($file));
}
I put in above code some constants because its values depends on your application.
I'm building an admin utility for adding a bulk of images to an app I'm working on. I also need to to log certain properties that are associated with the images and then store it all into the database.
So basically the script looks into a folder, compares the contents of the folder to records in the database. All of the info must be entered in order for the database record to be complete, hence the form validation.
The validation is working, when there are no values entered it prompts the entry of the missing fields. However it happens even when the fields ARE filled.
I'm doing something a bit funny which may be the reason.
Because I'm adding a bulk of images I'm creating the data within a for loop and adding the validation rules within the same for loop.
Here is the results:
http://s75151.gridserver.com/CI_staging/index.php/admin_panel/bulk_emo_update
Right now I have default test values in the form while testing validation. The submit button is way at the bottom. I'm printing POST variable for testing purposes.
Here is the code:
function bulk_emo_update() {
$img_folder_location = 'img/moodtracker/emos/';//set an image path
$emo_files = $this->mood_model->get_emo_images('*.{png,jpg,jpeg,gif}', $img_folder_location); //grab files from folder
$emo_records = $this->mood_model->get_all_emos(); //grab records from db
$i=1; //sets a counter to be referenced in the form
$temp_emo_info = array(); //temp vairable for holding emo data that will be sent to the form
//loop through all the files in the designated folder
foreach($emo_files as $file) {
$file_path = $img_folder_location.$file;//builds the path out of the flder location and the file name
//loops through all the database reocrds for the pupose of checking to see if the image file is preasent in the record
foreach($emo_records as $record) {
//compairs file paths, if they are the
if($record->picture_url != $file_path) {
//FORM VALIDATION STUFF:
$rules['segment_radio['.$i.']'] = "required";
$rules['emo_name_text_feild['.$i.']'] = "required";
//populating the temp array which will be used to construct the form
$temp_emo_info[$i]['path'] = $file_path;
$temp_emo_info[$i]['name'] = $file;
}
}
$i++;
}
//sets the reference to validation rules
$this->validation->set_rules($rules);
//checks to see if the form has all it's required fields
if ($this->validation->run() == FALSE) { //if validation fails:
print_r($_POST);
//prepairs the data array to pass into the view to build the form
$data['title'] = 'Bulk Emo Update';
$data['intro_text'] = 'fill out all fields below. hit submit when finished';
$data['emos_info'] = $temp_emo_info;
$this->load->view('admin_bulk_emo_update_view',$data);
} else { // if it succeeds:
//printing for test purposes
print_r($_POST);
$this->load->view('form_result');
}
}
I'm new to codeigniter and php in general so if anything looks outrageously weird please tell me, don't worry about my feelings I've got thick skin.
if ($this->validation->run() == FALSE)
if you are calling the run() method of the validation class every time the script is run, will it ever return TRUE and run the else? Maybe a different return?
I'm a little cornfused by what's going on. Generally, if I'm having a problem like this, I will figure out a way to force the result I'm looking for. e.g. in your code, I'd force that else to run... once I get it to run, break down what happened to make it run. Rudimentary, but it has served me well.
You use array of rules in
$this->form_validation->set_rules()
wrong.
If you want to pass the rules in array you must stick to the key names like described here http://codeigniter.com/user_guide/libraries/form_validation.html#validationrulesasarray
So instead of
$rules['input_name'] = "required"
try this:
array(
'field' => 'input_name',
'label' => 'Name that you output in error message',
'rules' => 'required'
)