i'm developing an application in Laravel but the thing is: my client already have a wordpress website and wants all registrations made in this website to go automatically to my application. I'm using mysql and the wp website too.
Can anyone give me a light here?
Thanks and sorry for my bad english.
I will try to give a basic workflow concept.
Do you want that, user will register in wp site, and that time he will be added/registered in the laravel application as well ? If so, then,
Create a user table, User model and userController with a 'store' method in laravel app. This 'store' method will create the user. The table's column names would be better to match the wp site's wp_users table columns name.
Now create an api route in laravel app that will take user data as post parameters. This user data will come from wp site after registration. The api route could be something like this
Route::post('store', 'userController#store')->name('users.store');
Now in wp site , place this code in 'user_register' hook. This code calls that store api of laravel app and pass the user data of that registered user as user data.
add_action( 'user_register', 'my_registration_save', 10, 1 );
function my_registration_save( $user_id ) {
$user = get_userdata($user_id);
//api call
wp_remote_post( the_api_url, array(
'user_email' => $user->user_email,
'user_login' => $user->user_login
...
...
) )
}
Now the wp site is sending the data through the api, your userController's store method have the access of that data. Use that data to store it in laravel's db, the userController's store method will be something like this
function store( Request $request) {
$user = new App\User();
$user->user_email = $request->user_email,
$user->user_login = $request->user_login
...
...
$user->save()
}
That's it.
Related
I am building an app using Yii2 and I am working with multi-tenant architecture. So... every client has his own database (identical structure).
What I have done so far:
I declare all the different databases in the config/web.php file
I have a master database that corresponds each user to his database. So, when someone logs in, the app knows what database should use.
What I have done but I am not sure about:
I created a file components/ActiveRecord.php with the following code:
<?php
namespace app\components;
use Yii;
class ActiveRecord extends \yii\db\ActiveRecord {
public static function getDb() {
if (isset($_SESSION['userdb'])) {
$currentDB = $_SESSION['userdb'];
return Yii::$app->get($currentDB);
}
}
}?>
So... on login I save the database on the session and in the aforementioned file which extends the default ActiveRecord I override the getDb function and I choose my own. Subsequently, I changed all models so they extend my ActiveRecord.
I am not sure that this strategy is correct but it almost works.
Where is the problem:
Everything works fine except from... RBAC! For RBAC I use the yii2-rbac extension. The problem is that the user is not getting his role from his database but from the first declared database in the config/web.php file. So, whatever the logged in user, the first db is used.
Question(s):
How can I solve this problem? Do you have any idea on where is the file that gives the role to the logged in user?
Bonus Questions: Do you think this strategy is wrong? If so, what would you suggest?
Thanks a lot in advance for your time and your support.
Question # 1: How can I solve this problem? Do you have any idea on where is the file that gives the role to the logged in user?
I would suggest you use yii2 admin extension for this purpose(https://github.com/mdmsoft/yii2-admin) that will solve your issue and it is the best extension to manage user role. use this link for better understanding (https://github.com/mdmsoft/yii2-admin/blob/master/docs/guide/configuration.md)
Install above by following above URL or just add "mdmsoft/yii2-admin": "~2.0" in your composer.json file and run composer update.
After successfully installed this extension run migration to create RBAC tables, if you already have then skipped it.
yii migrate --migrationPath=#yii/rbac/migrations
You have to do some configuration in your main.php to tell your application about public routes and for all other application route system will implement RBAC on them.
This is what you have to add in your main.php file.
'components' => [],
'as access' => [
'class' => 'mdm\admin\components\AccessControl',
'allowActions' => [
'site/login', // add or remove allowed actions to this list
'site/logout',
'site/error',
'site/index',
]
]
Above settings will tell your application to make the login, logout, error and index function are public under site controller and all other applications routes need to have RBAC assignment to perform the action.
main.php is exist in backend/config/main.php in my case, you can use according to your requirements may be in common/config/main.php
Question # 2: Bonus Questions: Do you think this strategy is wrong? If so, what would you suggest?
I think your approach is not extendable, I suggest you create a master database and use that for your application tenants with their databases.
Setup tenant table in master database with tenant name, database required parameters
Make master database connection in your application, that is used to get all tenant and there store DB connections from the master database.
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=127.0.0.1;dbname=master-db',
'username' => 'root',
'password' => 'root',
'charset' => 'utf8',
]
Now at login page show tenants list to choose their info OR you can also play with the domain name as well if you are using the unique domain for each tenant. if you are using unique domain then you have to store domain name with tenant info in the master database to able to get tenant info based on the domain.
// Set Session Values on success login page OR read user domain and get tenant info from the master database and add into session.
``
$tenant = Tenant::findOne(Yii::$app->request->post('tenant_id'));
Yii::$app->session->set('DB_HOST', $tenant->DB_host);
Yii::$app->session->set('DB_USER', $tenant->DB_username);
Yii::$app->session->set('DB_PASS', $tenant->DB_password);
Yii::$app->session->set('DB_NAME', $tenant->DB_name);
``
Once you have tenant info you can get the tenant from the master database and add their database settings into SESSION.
Create a BaseModel.php class and extend it with all of your application models classes.
In you BaseModel.php add below method to make runtime DB connection based on domain or tenant selection from the login page.
public static function getDb(){
if ( Yii::$app->session->get('DB_HOST') ){
$host = Yii::$app->session->get('DB_HOST');
$dbName = Yii::$app->session->get('DB_NAME');
$dsn = "mysql:host=$host;dbname=$dbName";
Yii::$app->db->dsn = $dsn;
Yii::$app->db->username = Yii::$app->session->get('DB_USER');
Yii::$app->db->password = Yii::$app->session->get('DB_PASS');
return Yii::$app->db;
}
}
By doing this you will have the option to add multiple tenants from backend to master database and that will automatically available in your application.
I believe that this information is helpful for you.
Cheers!!!
Here is the documentation on dbmanager.
If the you want to get rbac info from a different database, this should work.
Inside your config folder, create a file called rbacdb.php. Add the following:
<?php
return [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=<db host or ip>;dbname=<dbname>',
'username' => '<dbuser>',
'password' => '<dbPassword>',
'charset' => 'utf8',
];
Then go to your config file and find the authmanger section. It should look like this:
'authManager' => [
'class' => 'yii\rbac\DbManager',
'db'=> require(__DIR__ . '/rbacdb.php'),
'assignmentTable'=>'<tableName>',
'itemChildTable'=>'<tableName>',
'itemTable'=>'<tableName>',
'ruleTable'=>'<tableName>'
]
EDIT: after rereading your post...each user doesn't need their own rbac table/schema. use the system that Yii has in place.
Hope that you can help me.
I have a website that runs wooccommerce. I am using the woocommerce rest api. Now on another website what I want to do is create a simple search field where I type something and the search form needs to search through the woocommerce website and return results.
Is there a way I can achieve that ?
Try this:
/wp-json/wc/v2/products?search={{product_name}}
Works for me.
I think no.
The New Version of WooCommerce API (v2) is supports id based calls.
so instead you can get a list of abstract product details in your 2nd website and call back via product id.
/wp-json/wc/v2/products?search={{product_name}}
Is this function working if you are looking a exact product?
If you have a product like MR2050 and another with MR2050K, the result is not as you may expected, cause API rest will return 2 products, not just ONE?
If you use a wc-api-php (PHP library), please follow like this :
require __DIR__ . '/vendor/autoload.php';
use Automattic\WooCommerce\Client;
$woocommerce = new Client(
'http://mydomain', // Your store URL
'ck_****', // Your consumer key
'cs_****', // Your consumer secret
[
'wp_api' => true, // Enable the WP REST API integration
'version' => 'wc/v3' // WooCommerce WP REST API version
]
);
echo "<pre>";
print_r($woocommerce->get('products', ['search' => 'key word']));
echo "</pre>";
This works for me in 2021:
/wp-json/wc/v3/products?search={{productName}}
productName - refers to the input that you enter in the Search box
let's say I'm making ecommerce app with Yii2 and would like to implement all payment methods as modules.
After order has been confirmed by user, I would like to redirect user to payment process. I have following code in my CheckoutController:
if($order->save())
{
$module = Yii::$app->getModule('payment');
$module->init();
}
At this point I would like to share current Order $order instance with payment module.
What would be the best approach to do this?
I've looked through docs but did not find anything relevant.
Thank you!
In your payment module create a method setOrder($order) which sets the current order, checks if it is an instance of Order and so on.
Create another method like process() which does the payment processing. You should check here, if the $order is properly set.
You can then do in your CheckoutController:
if ($order->save())
{
$module = Yii::$app->getModule('payment');
$module->init(); // I believe yii calls this automatically
$module->setOrder($order);
$module->process();
}
I have a small app where users create things that are assigned to them.
There are multiple users but all the things are in the same table.
I show the things belonging to a user by retrieving all the things with that user's id but nothing would prevent a user to see another user's things by manually typing the thing's ID in the URL.
Also when a user wants to create a new thing, I have a validation rule set to unique but obviously if someone else has a thing with the same name, that's not going to work.
Is there a way in my Eloquent Model to specify that all interactions should only be allowed for things belonging to the logged in user?
This would mean that when a user tries to go to /thing/edit and that he doesn't own that thing he would get an error message.
The best way to do this would be to check that a "thing" belongs to a user in the controller for the "thing".
For example, in the controller, you could do this:
// Assumes that the controller receives $thing_id from the route.
$thing = Things::find($thing_id); // Or how ever you retrieve the requested thing.
// Assumes that you have a 'user_id' column in your "things" table.
if( $thing->user_id == Auth::user()->id ) {
//Thing belongs to the user, display thing.
} else {
// Thing does not belong to the current user, display error.
}
The same could also be accomplished using relational tables.
// Get the thing based on current user, and a thing id
// from somewhere, possibly passed through route.
// This assumes that the controller receives $thing_id from the route.
$thing = Users::find(Auth::user()->id)->things()->where('id', '=', $thing_id)->first();
if( $thing ) {
// Display Thing
} else {
// Display access denied error.
}
The 3rd Option:
// Same as the second option, but with firstOrFail().
$thing = Users::find(Auth::user()->id)->things()->where('id', '=', $thing_id)->firstOrFail();
// No if statement is needed, as the app will throw a 404 error
// (or exception if errors are on)
Correct me if I am wrong, I am still a novice with laravel myself. But I believe this is what you are looking to do. I can't help all that much more without seeing the code for your "thing", the "thing" route, or the "thing" controller or how your "thing" model is setup using eloquent (if you use eloquent).
I think the functionality you're looking for can be achieved using Authority (this package is based off of the rails CanCan gem by Ryan Bates): https://github.com/machuga/authority-l4.
First, you'll need to define your authority rules (see the examples in the docs) and then you can add filters to specific routes that have an id in them (edit, show, destroy) and inside the filter you can check your authority permissions to determine if the current user should be able to access the resource in question.
I'm currently trying to override Wordpress' wp_authenticate function (without modifying the core files, mainly pluggable.php), however I'm not sure if I'm going about it the correct way. There are two great references (see below), but they don't explicitly state what to do in order to prevent the login provided certain criteria are met.
In short, I'm trying to prevent registered users who have not activated their account. I've already implemented creating a user with a md5 unique id in the usermeta table (attached to their user id). I'm basically trying to check for that "activation_key' value in the usermeta table on login, if a value exists, I want to prevent the login from occurring.
The authenticate filter seems to be exactly what I need but after modifying it and placing it into my functions.php file, it doesn't seem to work! Login occurs per usual.
References:
How do I hook into the Wordpress login system to stop some users programmatically?
http://willnorris.com/2009/03/authentication-in-wordpress-28
I actually found a work around.
Using a custom form you can log into Wordpress using the wp_signon function.
var $creds = array();
$creds['user_login'] = 'example';
$creds['user_password'] = 'plaintextpw';
$creds['remember'] = true;
//check if user has an activation key in the usermeta table
$user = get_userdatabylogin($creds['user_login']);
if(get_usermeta($user->ID,'activation_key')) {
} else {
$procLogin = wp_signon( $creds, false );
if ( is_wp_error($procLogin) ) {
echo $user->get_error_message();
}
echo 'success!';
}
hope this helps someone out there