How do I run CodeIgniter migrations? - codeigniter

I know how to create them via http://codeigniter.com/user_guide/libraries/migration.html
But once I've created my migration files, how do I run them?

Using these pages as references: Running via the CLI
and Migration Class
you're able to restrict access to your migration controller to command line with something along these lines (application/controllers/migrate.php):
<?php if ( ! defined('BASEPATH')) exit("No direct script access allowed");
class Migrate extends CI_Controller {
public function __construct()
{
parent::__construct();
$this->input->is_cli_request()
or exit("Execute via command line: php index.php migrate");
$this->load->library('migration');
}
public function index()
{
if(!$this->migration->latest())
{
show_error($this->migration->error_string());
}
}
}
then to execute your latest migration, cd into the root of your project directory and run:
php index.php migrate
but when you attempt to access via webserver example.com/migrate you will see the text in the script above.

I am not sure this is the right way to do it, But It works for me.
I created a controller named migrate (controllers/migrate.php).
<?php defined("BASEPATH") or exit("No direct script access allowed");
class Migrate extends CI_Controller{
public function index($version){
$this->load->library("migration");
if(!$this->migration->version($version)){
show_error($this->migration->error_string());
}
}
}
Then from browser I will call this url to execute index action in migrate controller
Eg : http://localhost/index.php/migrate/index/1

You can also run some version for down or up migrations:
if(!defined('BASEPATH')) exit('No direct script access allowed');
class Migrate extends CI_Controller{
public function __construct()
{
parent::__construct();
$this->load->library('migration');
}
public function version($version)
{
if($this->input->is_cli_request())
{
$migration = $this->migration->version($version);
if(!$migration)
{
echo $this->migration->error_string();
}
else
{
echo 'Migration(s) done'.PHP_EOL;
}
}
else
{
show_error('You don\'t have permission for this action');;
}
}
}
For CLI run this command php index.php migrate version 5, where 5 is version of migration. If version is more of current migration - migration up, else - down to entered version.

This is simplest Codeigniter Database Migrations
Configure application/database.php to your database name settings.
Create application/config mirate.php
<?php defined("BASEPATH") or exit("No direct script access allowed");
class Migrate extends CI_Controller
{
public function index()
{
if (ENVIRONMENT == 'development') {
$this->load->library('migration');
if (!$this->migration->current()) {
show_error($this->migration->error_string());
} else {
echo "success";
}
} else {
echo "go away";
}
}
}
In application\migration.php, change $config['migration_enabled'] = TRUE; .
open CLI in folder and type php index.php migrate

I think I have the simplest solution around here. (This is for Codeigniter 3.1.11)
The solutions above either suggest doing the migration through url or cli.
Problem with the first one is you make this should-be-behind-the-scenes issue publicly available.
Problem with the second one is if you are deploying this project on shared hosting platform you don't have the chance to run it via cli.
So the simplest solution to my opinion is to let codeigniter do the work for us:
(assuming that you have done your database settings and created migrations properly)
make $config['migration_enabled'] = TRUE; in /application/config/migration.php
define migration version $config['migration_version'] = 20201019123900; like this
set $config['migration_auto_latest'] = TRUE;
autoload or manually load migration library (define it in /application/config/autoload.php like $autoload['libraries'] = array('migration'); or load it in controller constructor like $this->load->library('migration');)
and just run your application (open it via browser)
Tata! There you go. You can check your database if your tables have been created correctly.
It should be OK for development environment to leave the settings like this.
BUT for production environment we should reset $config['migration_enabled'] = FALSE; as it is pointed out in the comment section.
This solution might be criticized because migration library is loaded each time the application or the controller is run but I haven't said it's the best solution, I have said it's the simplest solution.

In application\migration.php, change $config['migration_enabled'] = TRUE; .this is the actual CI migration.php file path right
You said that application\migration.php, actual is application\config\migration.php.

<?php defined("BASEPATH") or exit("No direct script access allowed");
class Migrate extends CI_Controller
{
public function index()
{
if (ENVIRONMENT == 'development') {
$this->load->library('migration');
if (!$this->migration->current()) {
show_error($this->migration->error_string());
} else {
echo "success";
}
} else {
echo "go away";
}
}enter code here
}

A CI version 4 answer (2022):
In version 4 it is slightly different: https://codeigniter.com/user_guide/dbmgmt/migration.html
namespace App\Controllers;
use CodeIgniter\Controller;
use Throwable;
class Migrate extends Controller {
public function index(){
$migrate = \Config\Services::migrations();
try {
$migrate->latest();
$migrate->regress();
echo 'Migration complete';
} catch (Throwable $e) {
print'<pre>';print_r($e);print'</pre>';
}
}
}
Note I've included the regress option if you wish to roll back your migrations as well.

Related

Can we exclude a custom service provider when running php artisan migrate in laravel?

I have a custom service provider in which I am accessing a model in boot(). But when I run php artisan migrate, it shows the below error:
[Illuminate\Database\QueryException] SQLSTATE[42S02]: Base table or view not found: 1146 Table '********' doesn't exist
I found that if we add if (!app()->runningInConsole()) { inside boot(), it works successfully.
This is the code we have used in the service provider:
public function boot()
{
$this->bindCurrentPartToNav();
}
private function bindCurrentPartToNav(): void
{
$currentPartName = \App\Http\Helpers\Part::getPartName();
view()->composer(
'includes.partials.part',
function ($view) use ($currentPartName) {
$view->with('currentPartName', $currentPartName);
}
);
}
Helper file:
public static function getPartName(): ?string
{
return PartModel::PartKey()->active()->pluck('name')->first();
}
Model:
public function scopePartKey($query): Builder
{
return $query->where('identifier', config('env.PART_KEY'));
}
Is there any way to remove that service provider from php artisan migrate so that we can remove runningInConsole() check in each refresh?
Thanks for your help in advance.
As any environment configuration, in your case a general configuration, you should assign a default value fall back.
public static function getSectionName(): ?string
{
try {
return SectionModel::sectionKey()->active()->pluck('name')->first();
} catch (\Exception $e) {
return null;
}
}
This will simulate the case where the section model with that specific identification_key is missing in the database.
This will also prevent any issues with the initial migration.
But in the end, you tied a model with a view rendering code. You should find another solution to dissociate them. For example, you can move the boot() code out of the model and link it to a middleware.
You can also use Singleton pattern (since it's like a general unique config across the application)

How to extend Code igniter cache class Redis class

I am using redis for caching in one of my assignment. I am using CI default redis library for this purpose.
Now the issue with library is that it has some specific set of method which are used to set, get, delete , increment and decrement the redis keys & values.
I want to additional function of redis like lpush, rpush,lrem, lrange etc.
So to achieve this , i am trying to extend default CI redis class. which i am putting in application/libraries/driver/cache_redis_extended.php.
my code for this class is as follow.
<?php defined('BASEPATH') OR exit('No direct script access allowed');
class Cache_redis_extended extends CI_Cache_redis
{
function __construct()
{
parent::self;
}
public function rpush($list, $data)
{
$push = $this->_redis->multi(Redis::PIPELINE);
return $push->rpush($list, json_encode($data));
}
public function lrem($list, $data)
{
if((is_string($data) && (is_object(json_decode($data)) || is_array(json_decode($data))))) {
$data = $data;
}else{
json_encode($data);
}
return $this->_redis->lrem($list,-1, $data);
}
public function __destruct()
{
if ($this->_redis)
{
$this->_redis->close();
}
}
}
and in my model I am loading this class as follows
$CI->load->driver('cache', array('adapter' => 'redis'));
But I get this error:
Unable to load the requested class: cache_redis_extended
Any help is appreciated for this issue.
As I can see your driver name is not started with Capitalized , so
it can be possible the cause of your issue.
Because according to codeigniter the naming rule of a class as follows
Naming Conventions
File names must be capitalized. For example: Myclass.php
Class declarations must be capitalized. For example: class Myclass
Class names and file names must match.
change your file name
from cache_redis_extended.php
to Cache_redis_extended.php
I hope it will be helpful for you.

How to interact with prestashop data using ajax?

I have a prestashop store, I wish to add some interactivity in the shop but for that purpose I need to fetch some data about the products from the database. I tried to search the prestashop docs but didn't find anything useful.
How can I interact with prestashop's products data using ajax?
You can make a php file where you want (root folder is ok) and and start the "enviroment" like this
require_once(dirname(__FILE__).'../../../config/config.inc.php');
require_once(dirname(__FILE__).'../../../init.php');
echo("<br />a log string " . date("H:i:s d/m/Y"));
error_reporting(E_ALL ^ E_NOTICE ^ E_STRICT);
// here you have all prestashop class
$myCategory = new Category($id)
after that you reach your's php in your ajax call
1- Go to : https://validator.prestashop.com/auth/login
2- create a generic module (more fast)
3- create folder controllers/front/ajaxmain.php (example)
add:
<?php
class YOURMODULENAMEAjaxmainModuleFrontController extends ModuleFrontController
{
public function __construct()
{
parent::__construct();
$this->context = Context::getContext();
}
public function initContent()
{
parent::initContent();
if (Tools::isSubmit('anysubmitname'))
{
$this->getproduct();
}
//or Tools::getvalue("anyvalue")....
}
private function getproduct(){
// do your magic
die(json_encode(array(
"response"=> "response"
) ));
}
Then, call it -> index.php?fc=module&module=test&controller=ajaxmain
I think that this is more clean, then you can get more things with this

How can I use CodeIgniter's active record (or models) object in a command line script?

Title pretty much sums it up. I'd like to write a script to import some data from a third party. Is there any way I can get either an instance of CodeIgniter's Active Record class, or of a particular model inside of an a script that can be run from the command line?
Say you have your CodeIgnited application inside ignited/, you have your command line script running in cli/. Here is your folder layout:
ignited/
application/
system/
index.php
cli/
mycli.php
Now you want cli/mycli.php to use some model from ignited/
First, you should do something with your ignited app:
Modify your default controller (which is set in ignited/application/config/routes.php). For example ignited/application/controllers/welcome.php:
class Welcome extends CI_Controller {
public function index()
{
$this->load->view('welcome_message');
}
}
add these code:
if ($this->input->is_cli_request())
{
return;
}
so it would look like:
class Welcome extends CI_Controller {
public function index()
{
if ($this->input->is_cli_request())
{
return;
}
$this->load->view('welcome_message');
}
}
For testing, I created a test model ignited/application/models/do_nothing_model.php:
class Do_nothing_model extends CI_Model {
public function __construct()
{
parent::__construct();
}
public function do_nothing()
{
return "Do nothing";
}
}
OK! Now try this in cli/mycli.php:
require_once('../ignited/index.php');
$ci =& get_instance();
$ci->load->model('do_nothing_model');
echo $ci->do_nothing_model->do_nothing();
Drawback: unable to run the default action of your default controller in command line
UPDATE 2012-06-08: from CodeIgniter Wiki
Not sure if this is what you want, but if you just need to run CI from CLI, here is the userguide reference:
http://codeigniter.com/user_guide/general/cli.html
To clarify, you don't need it web facing, just setup your app and run the commands you need (controller method input):
$ php index.php tools message "John Smith"
that example would run the primary index.php file for CI, then the tools controller and method message, "John Smith" is your input to message (could be a file reference that is local on the machine for your file import).

Codeigniter template library and HMVC ( mx library ) the static method run()

i have this testing code which am working with ..
i have a module called ms and and another one called test
the test controller code is :
<?php
class Test extends MX_Controller {
public function __construct()
{
parent::__construct();
$this->template->title($this->config->item('site_name','app'));
}
public function index()
{
$this->template->build('index');
}
}
and the code inside ms is :
<?php
//ms module
class Msrofi extends MX_Controller {
public function __construct()
{
parent::__construct();
$this->template->title($this->config->item('site_name','app'));
}
public function index()
{
$t = Modules::run('test/test/index');
var_dump($t);
$this->template->build('index_message');
}
}
the problem is that the build function inside test is trying to find the index view file inside the ms views folder not the test views folder ..
i checked the $this->_module and it gave me the ms module name ..
any one know how to fix that ??
Since the test module is being called in the context of the ms one, $this->template->build() is looking for a view file in the ms module. The same way you can load models and libraries cross-module, you would have to do this for your view path as well:
class Test extends MX_Controller {
public function index()
{
// This path works only from the "test" module
// $this->template->build('index');
// This path works from any module
$this->template->build('test/index');
}
}
It's a little annoying maybe to have to explicitly call the module path in the module itself, but cross-module dependency defeat some of the goals of modularity in the first place.
A quick aside: Modules::run() output not returned, but directly echoed, so you can't assign it to a variable or print_r/var_dump it without using an output buffer:
ob_start();
Modules::run('test/test/index');
$t = ob_get_clean();
var_dump($t);
You can try to change the module.php the run method
The following example is I have to use the fix solution:
Open the third_party/MX/Modules.php
Near 75 lines to find
$buffer = ob_get_clean();
Increase in its following:
if($output === NULL && $buffer === ''){
$output = CI::$APP->output->get_output();
}
At this time, it should be able to work properly...

Resources